Local proxy for Forex Forge API currency conversion
please add the api key for Forge API in application.conf
file
BlazeHttpClient` is injected in corresponding services on the the app init
One basic route is used GET /rates?from={from}&to={to}
Errors from services are mapped to specific program ones with diff Http codes
Added validation for parsed query params
One program uses 2 services RatesService
and QuotaService
and a simple `Cache
Main flow is simple:`
- we check for the currency pair in the cache is nothing found (or cache entry is out-of-date)
- we check if quota is not yet used up
- then we check for rates
- if rate is returned we update the cache
(!) there's '/market' API exposed by Forge so we could check in the beginning of the flow if it's open/closed but I guess it's not adding a lot to the exercise cause it will be basically the same check as for quota
Calls Forge API : https://forex.1forge.com/1.0.3/quota?api_key={{api_key}}
If quota is used up we return a specific error.
Calls Forge API : https://forex.1forge.com/1.0.3/convert?from={{from}}&to=={{from}}&quantity=1&api_key={{api_key}}
and returns conversion information.
Simple cache is used backed up by Ref[F, Map[Rate.Pair, (Rate, Timestamp)]]
Check for time-to-live happens on access, if entry is found but it's alreadt too old I return None
which triggers a call to the API and subsequent cache update in the main program flow.
(!) Probaly on a real world scenario for a more generic cache a process running in the background that evicts an old entries is more appropriated but I guess since cache for currency pairs is really small it looks good enough for the exercise
In general Forge API is quite leaky and inconsistent. In some cases proper HTTP error codes are used and in some just 200 with some error fields.
In general in services I tried to treat both cases and took some shortcuts in matching all error codes in the same way. I guess that for the final user difference between a bad request (from a service call) or server error is not really relevant.
Errors are typed and mapped to specific Program errors
Requests and responses are logged.
Unit tests for :
- service live interpreters
- main program
Used standard Logging
middleware for incoming HttpCalls as well for the ones we emit via HttpClient
-
logging without correlation id is not that useful. investigate : https://gvolpe.github.io/http4s-tracer/
-
better centralized error management for routes (HttpErrorHandler)