sk112 / fetch_rewards_test

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fetch Reward Test

Background

Our users have points in their accounts. Users only see a single balance in their accounts. But for reporting purposes we actually track their points per payer/partner. In our system, each transaction record contains: payer (string), points (integer), timestamp (date).

For earning points it is easy to assign a payer, we know which actions earned the points. And thus which partner should be paying for the points. When a user spends points, they don't know or care which payer the points come from. But, our accounting team does care how the points are spent.

There are two rules for determining what points to "spend" first:

  • We want the oldest points to be spent first (oldest based on transaction timestamp, not the order they’re received)
  • We want no payer's points to go negative.

Execution Steps

  • To start the server using npm, run the following command at root

    $ npm start
    
  • To start the server using nodemon, run the following command at root

    $ nodemon
    
  • To run tests, run the following command at root.

    $ npm test
    

For any modifications, modify package.json or nodemon.json files for npm and nodemon respectively.

Files Structure

.
+-- index.js 
+-- main.js
+-- util.js
+-- impl.js
+-- test
|   +-- app.test.js
|   +-- test-constants.js
+-- package.json
+-- nodemon.json
+-- ReadMe.md

Details

  • Entry point is index.js
  • util.js contains implementation of common functions needed for the main functionality.
  • impl.js is the implementation of main functionality of the end points.
  • test folder contains the test case related files.
  • package.json, nodemon.js are configuration files needed for npm and nodemon respectively.

End points

POST /add Pushes the record into the database.

API End point

POST http://localhost:9090/add

Request Body Format:
{
    "payer": "[payer-name]",
    "points": [points],
    "timestamp": "[timestamp]" [sample format: "2021-03-01T14:00:00Z"]
}

Returns

  • The request returns status code 200 and {code:200, msg: 'success'} upon successful add operation.
  • Returns status code 400 and {code:200, msg: <error-msg>} for failures.

Example

Request:
POST http://localhost:9090/add
{
    "payer": "DANNON1",
    "points": -200,
    "timestamp": "2021-03-01T14:00:00Z"
}

Response:
{
  "code": 200,
  "msg": "success"
}
POST /spend This request calculates the points spent from each payer from the records sorted based on the timestamp.

API End point

POST http://localhost:9090/spend

Request Body Format:
{
    "points": [points-to-spend],
}

Returns

  • List of all spent payers along with their points.
  • If the points are insufficient or not available, then Spend Fail property will appear in the response [Spend Fail: [points]]

Example

Request:
POST http://localhost:9090/spend
{
    "points": 450
}

Response:
{
    "DANNON1": 200,
    "Spend Fail": 250
}
GET /balance Returns the available points from each payer.

API End point

GET http://localhost:9090/balance

Returns

  • List of all payer remaining points.
  • Returns empty list if none of the payers has any points.

Example

Request:
GET http://localhost:9090/balance

Response:
{
  "DANNON1": 200
}

Flow

Explanation:

  • The Server will listen on 9090 port.
  • There are three end points provided as explained in End points section.
  • Server pushes the record to the Database for every add request and updates the record in Data based on the timestamp.
  • Servers requests data from Data for every spend and balance request.
  • The original data is kept untouched in the Database. all the operations are performed on Data object
  • Thus, the Data and the Database will remain in sync at all times.

The Data and the Database here are just two variables in the implementation.

Implementation

  • The Data is sorted every time a new record is inserted into the Database for record retrieval with low timestamp for spend requests.
  • The sort is implemented using Low bound binary Search and Insertion sort approaches.
  • For every record inserted, We get index to insert the record into the Data using Low bound binary Search.
  • For spend requests, the points are calculated from 0 index, every time all points are used, the 0th record in the Data is deleted and every record in the right of 0 index will shift right.

    This may cause performance complexity since shifting records every time is expensive. to avoid this heap trees can be used which reduces the complexity from O(n) to O(logn) for delete operation.


About


Languages

Language:JavaScript 100.0%