Skip to content

mikejdorm/rate-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rate API

The following document provides details on the Rate API including definition of the available routes, and design decisions with the architecture of the API.

Building the Project

The following command will build the project and run all the unit tests.

./gradlew clean build

Running the tests

Unit tests can be run through the following command.

./gradlew test

Note: A test report is generated following the test run with the location of the test file being part of the output of the test command.

Starting the Server

After building the project, the following command will start the server using the jar file generated by the build command.

java -jar build/libs/rate-api-0.1.0.jar

Routes

Get Rate

In to retrieve a rate based on a start date time and end date time the following endpoint is provided

  • Example
    curl -G -v http://localhost:8081/v1/rate --data-urlencode "startDateTime=2015-07-01T07:00:00-05:00" --data-urlencode "endDateTime=2015-07-01T12:00:00-05:00"
    
  • Route - /v1/rate
  • Method - GET
  • Query Params
    • startDateTime - the start date and time formatted as a
    • endDateTime - the end date and time formatted as a
  • Response Body
    {
      "price": 1750,
      "status": "available",
      "startDateTime": "2015-07-01T07:00-05:00",
      "endDateTime": "2015-07-01T12:00-05:00"
    }
    

Post Rates

Rates can be updated in memory within the API by posting a new set of rates as a JSON body

  • Example Request
     curl -v -XPOST http://localhost:8081/v1/rate -d '
      {
        "rates": [
            {
                "days": "mon,tues,thurs",
                "times": "0900-2100",
                "tz": "America/Chicago",
                "price": 1500
            }
          ]
        }'
    
  • Route - /v1/rate
  • Method - POST
  • Request Body
    {
        "rates": [
            {
                "days": "mon,tues,thurs",
                "times": "0900-2100",
                "tz": "America/Chicago",
                "price": 1500
            },
            {
                "days": "fri,sat,sun",
                "times": "0900-2100",
                "tz": "America/Chicago",
                "price": 2000
            },
            {
                "days": "wed",
                "times": "0600-1800",
                "tz": "America/Chicago",
                "price": 1750
            },
            {
                "days": "mon,wed,sat",
                "times": "0100-0500",
                "tz": "America/Chicago",
                "price": 1000
            },
            {
                "days": "sun,tues",
                "times": "0100-0700",
                "tz": "America/Chicago",
                "price": 925
            }
        ]
    }  
    
  • Response - 200 code if successful, 400 if a bad request

Metrics

Metrics for the individual endpoints can be retrieved through a GET requests

  • Example Request
    curl -v localhost:8081/v1/metrics | jq .
    
  • Route - /v1/metrics
  • Method - GET
  • Response Body
    [
      {
        "id": {
          "name": "http.server.request.latency",
          "tags": [
            {
              "key": "method",
              "value": "POST"
            },
            {
              "key": "path",
              "value": "v1_rate"
            },
            {
              "key": "status",
              "value": "200"
            }
          ],
          "type": "TIMER",
          "description": "Timing of server requests",
          "baseUnit": "seconds",
          "tagsAsIterable": [
            {
              "key": "method",
              "value": "POST"
            },
            {
              "key": "path",
              "value": "v1_rate"
            },
            {
              "key": "status",
              "value": "200"
            }
          ]
        }
      },
      ...
      {
        "id": {
          "name": "http.server.request.count",
          "tags": [
            {
              "key": "method",
              "value": "GET"
            },
            {
              "key": "path",
              "value": "v1_rate"
            },
            {
              "key": "status",
              "value": "400"
            }
          ],
          "type": "COUNTER",
          "description": "Total number of server requests",
          "baseUnit": null,
          "tagsAsIterable": [
            {
              "key": "method",
              "value": "GET"
            },
            {
              "key": "path",
              "value": "v1_rate"
            },
            {
              "key": "status",
              "value": "400"
            }
          ]
        }
      }
    

Swagger Docs

Documentation can be retrieved from the API through the following request. The swagger documents follow the OpenApi 3.0 format

  • Example Request
     curl -v localhost:8081/v1/api/swagger.json | jq .
    
  • Route - /v1/api/swagger.json
  • Method - GET
  • Response Body
    {
      "info": {
        "title": "Rate API",
        "version": "v1.0",
        "description": "This API stores and provides rates for given time ranges."
      },
      "tags": [],
      ...
    }
    

Design Decisions

This API is built entirely in Kotlin and uses the http4k library for defining the routes. This library provides several useful features which can be found on the their website linked earlier. For this project the main highlights were the following.

  • Immutability given the "Application as Function" design
  • Easy documentation since swagger documentation is integrated with the library
  • Simple to test using http4k test library
  • Easy integration of metrics reporting

I could have easily taken this further to make the underlying rates immutable by adding in a process to version the rates when an rate POST request is sent to updat the rates. However, the current state of the project works well as is with the explicit mutable map implementation.

I added a few notes within the [RateDao] on how the rates were stored within the API. The storage of the rates relies heavily on the guava library and specifically the [RangeMap] implementation within that library. This data structure is well suited to problems involving scheduling like the rates API. The time ranges can be stored as keys in the map so then retrieval of the rates can be done in two map lookups.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages