Project Structure
- The structure of my submission is similar to the original starter code.
- The
SmartcloudClientService
encapsulates the SmartCloud API and is responsible for making requests to the docker container. SmartApp
defines theHttpRoutes
used by the server.SmartServer
glues everything together into a working server instance.- The
MockClientService
serves dummy data so that my code can be tested independently of the docker container.
Running the Project
- To test the project:
sbt test
- To run the project:
- Make sure the docker container is running with
docker run -p 9999:9999 smartpayco/smartcloud:latest
- Then,
sbt run
will start a local server on port8080
.
- Make sure the docker container is running with
Endpoints
-
/instance-kinds
Queries the SmartCloud/instances
endpoint and returns the list of available instances, in a slightly different format.GET 0.0.0.0:8080/instance-kinds [ { "kind": "sc2-micro" }, { "kind": "sc2-small" }, ... { "kind": "sc2-hicpu-32" } ]
-
/prices?kind=<kind>
Queries the SmartCloud API for pricing information about the specified instance.GET 0.0.0.0:8080/prices?kind=sc2-small { "kind": "sc2-small", "amount": 0.471 }
Features
- When the SmartCloud API returns a
500 Internal Server Error
, the http client uses an exponential backoff retry policy to attempt to return a result.
Things that could be improved with more time:
- This is my first time writing
Scala
(as well ascats
,cats-effect
,http4s
). With more time/experience, I'd become more familiar with Scala idioms and best practices. - I don't handle the SmartCloud API's
529 Too Many Requests
when the rate limit is reached. I had difficulty figuring out how to elegantly handle different response status codes, mostly due to my lack of experience with Scala andhttp4s
. With more time, I would want to use some kind ofMonadError
(perhaps with a custom error type) to exit early from the main logic and invoke an error handler. Here's an example of some Haskell code I wrote using a similar pattern. - Test coverage is not 100%. For instance, I don't have any tests checking that
SmartServer
uses the configuration files correctly. I also don't have tests for theRetryPolicy
. - Since the Docker container which serves the SmartCloud API is rate-limited and prone to server failures, all of the tests currently use a
MockClientService
to test the behavior of the routes I implemented. Also, the tests only test theSmartApp
implementation, and I don't include any tests forSmartServer
, which runs the actual server. In a production setting, it would also be important to directly test the interaction between these local/remote servers. This would probably involve mocking the SmartCloud API so that it never fails (or, so that it fails in a controlled way) and running automated tests in a docker container.
Other possible improvements:
- The starter code contained an
InstanceKindsService
corresponding to the/instance-kinds
endpoint, suggesting that a/prices
endpoint should have a correspondingPriceService
, and so on. However, since these are the only two endpoints, and both simply "wrap" calls to an HTTP client, I implemented both in a singleClientService
, which abstracts away all API calls to the SmartCloud instance. For a larger application with more complex behavior, it might make sense to separate requests and response handling into a number of differentXYZService
s.
Important: Do NOT fork this repository if you want to submit a solution.
Imagine we run our infrastructure on a fictional cloud provider, Smartcloud. As their machine instance prices fluctuate all the time, Smartcloud provides an API for us to retrieve their prices in real time. This helps us in managing our cost.
Implement an API for fetching and returning machine instance prices from Smartcloud.
GET /prices?kind=sc2-micro
{"kind":"sc2-micro","amount":0.42}, ... (omitted)
This project scaffold provides an end-to-end implementation of an API endpoint which returns some dummy data. You should try to follow the same code structure.
You should implement SmartcloudPriceService
to call the smartcloud endpoint and return the price data. Note that the smartcloud service has usage quota and may return error occassionally to simulate unexpected errors. Please make sure your service is able to handle the constraint and errors gracefully.
You should also include a README file to document:-
- Any assumptions you make
- Any design decisions you make
- Instruction on how to run your code
You should use git and make small commits with meaningful commit messages as you implement your solution.
Follow the instruction at smartcloud to run the Docker container on your machine.
Clone or download this project onto your machine and run
$ sbt run
The API should be running on your port 8080.
Please push your code to a public repository and submit the link via email. Please do not fork this repository.