## Golang Assessment Tasks: 1. Create a post api which will have rate limit on basis of each and unique ip. 2. Demonstrate Command Design Pattern in Golang with Unit Tests 3. Using GIN Framework demonstrate custom binding request(At least give 5 field example with including boolean, pointers, int, string, runes. 4. Demonstrate Database Transaction of at least 10 different tables with proper error handling using a single api(use GIN). 5. Write SQL Queries for Department of Top Three Salaries 6. You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps. ### Implementation It was all very interesting tasks. I really enjoyed and hepled me with myself assessment. In the start, I tried TDD approach but things were getting complex along with deadline presure. Therefore, I moved with separate solution of each task and lastly combined into a service. ## Task-1 and Task6 I followed with my last online website observation that was providing 5 free calls a day for non-registered users based on IP. So I implemented the same subscription markting approach and allowed 5 calls a day for specific user. In the same POST api I implemented the staircase algorithm for entertainment and testing. #### Endpoint: `/task/oneandsix/mincoststairs` This endpoint include the solution to Task-6; the minimum cost to reach the top of a staircase using a one-step or six-step climb strategy. It was a good chellenge simple and planned. **Request** - **URL:** `http://localhost:6000/task/oneandsix/mincoststairs` - **Method:** POST - **Request Body:** JSON **Request Body Example** ```json { "integer-array": [10, 15, 20] } // Response { "mincost": 15 } ``` ![](https://hackmd.io/_uploads/rkgpBEuQf6.png) ## Task 5 It was a great task and chellenged me. I found it simple but took my good time. Here, how I approached this one. **Step-01**: To find distinct salaries. **QUERY**: ``` SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 3 ``` **Step-02**: To find Employees of top salaries. I detected the issue with my first sub-query that it wouldn't help in finding top 3 earners in each department. **QUERY**: ``` SELECT * FROM Employee JOIN (SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 3) AS TopSalaries ON Employee.Salary = TopSalaries.salary ``` **Step-03**: To find top three distinct earners in individual department. And I tried sub-query with hard-code values. **QUERY**: ``` SELECT DISTINCT salary FROM Employee WHERE Salary >= 70000 and departmentId = 1 ``` **Step-04**: Finally got the solution finding the rank of each employee in its department employees. Further, considering the output the result is ordered based on department and salary. **QUERY**: ``` SELECT d.Name AS Department, e1.Name AS Employee, e1.Salary AS Salary FROM Employee e1 JOIN Department d ON e1.departmentId = d.id WHERE (SELECT COUNT(DISTINCT e2.salary) FROM Employee e2 WHERE e2.departmentId = e1.departmentId AND e2.salary >= e1.salary) < 4 ORDER BY Department, Salary DESC ``` I also created a GET api and tested with the given data considering postgres database. Following are screenshots of its call on postman. **Request** - **URL:** `http://localhost:6000/task/five/highearners` - **Method:** GET - **Request Body:** Nil **Response** - status int - message string - data []map[string]interface{} ```jsonld { "status": 200, "message": "success", "data": [ { "department": "IT", "employee": "Max", "salary": 90000 }, { "department": "IT", "employee": "Joe", "salary": 85000 }, { "department": "IT", "employee": "Randy", "salary": 85000 }, { "department": "IT", "employee": "Will", "salary": 70000 }, { "department": "Sales", "employee": "Henry", "salary": 80000 }, { "department": "Sales", "employee": "Sam", "salary": 60000 } ] } ``` ![](https://hackmd.io/_uploads/BJzlv_mfa.png) The structure of the gin-gonic service that includes the task implemention is following; ``` ./assessment ├── config │   └── db.go ├── Dockerfile ├── go.mod ├── go.sum ├── main.go ├── Makefile ├── models │   └── models.go ├── README.md ├── responses │   └── responses.go ├── routes │   └── routes.go ├── services │   ├── custombinding.go │   ├── highearners.go │   ├── mincost.go │   └── transaction.go ├── tasktwo │   └── commandpattern │   ├── button.go │   ├── command.go │   ├── command_pattern_test.go │   ├── demote.go │   ├── employee.go │   ├── promote.go │   └── role.go └── utils ├── query.go ├── rate-limiter.go └── tables.go ``` ## Task-2 For Task-2 I implemented the command pattern and tried simplifying through separate files and demostrated through unit-test as mentioned using testing package. **Command** ```shell go test -v ./tasktwo/commandpattern/ ``` **Result** ```shell= === RUN TestPromoteEmployeeCommand Promoted Elon to CEO Promoted Elon to CEO --- PASS: TestPromoteEmployeeCommand (0.00s) === RUN TestDemoteEmployeeCommand Demoted Elon to Board Member --- PASS: TestDemoteEmployeeCommand (0.00s) PASS ok github.com/wasimkhandot01/assessment/tasktwo/commandpattern 0.003s ``` ## Task-3 In all API's I used gin's built-in binding functionality with customized data binding models. Further as per the task I utilized a json unmarshalling to perform some manaul approach. **Request** - **URL:** `http://localhost:6000/task/three/custombinding` - **Method:** POST - **Request Body:** JSON **Response** - status - message - error ```jsonld= { "status": 200, "message": "Received data: BoolField=true, IntField=42, StringField=Hello, JSON!, PointerField=0x12345678, Nested (Head=1, Tail=2)", "error": "nil" } ``` ![](https://hackmd.io/_uploads/ry8yaumG6.png) ## Task-4 I was wishing to discuss this task as it seemed to me a bit generalized. But as of Sunday I decided to make my own way on this. So I came with a transaction query on executing 11 tables creation queries. I have implmented the base of transaction which is rollback on failure of single operation. I was trying through *map* which is unordered and I was getting errors because of foreign keys dependencies. So I utilize it then as opportunity to demonstrate the transaction query behanvior. I implemented single API with different values of parameter. The function is same but if you pass *slice* as parameter the transaction will successfully comleted and if you pass *map* then the transaction might fail at some point and roll-back previous query execution and doesn't commit. **Request** - **URL:** `http://localhost:6000/task/four/transaction` - **Method:** POST - **Request Body:** JSON ```jsonld { "tool":"slice" //"map" } ``` **Response** ```jsonld= { "status": 200, "message": "success", "execution": "Tables are successfully created." } ``` **slice param** ![](https://hackmd.io/_uploads/HkU8lK7fa.png) **map param** ![](https://hackmd.io/_uploads/Bk8uxFmGa.png) Yeah, you can confirm the database creation by executing the *highearners* API. If that gives you error that means you executed this API with *slice* param and tables are created. There is an Employee table in common which make the other API fail. But As soon you try on *map* incase of failure all the tables will be rollbacked. I have been a bit generalized for the last month and might have missed with my technical show on unit-testing and some error handling consideration. But I tried to show my dedecation with utilizing my complete time. Thanks Cheers!