Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Forex Service — Interview Submission Notes
This document is not a runbook. It is a concise explanation of the engineering decisions made in this solution, with emphasis on architecture, trade-offs, and rationale.
Context
The task is to provide FX rates via HTTP while integrating with an external one-frame service under strict request limits.
The key constraints that shaped the design were:
pair=...repeated in query)200with body like{"error":"..."}Key Principles
What Was Implemented
1) Layered architecture aligned with Tagless Final
New/updated modules are grouped by responsibility:
forex.services.rates— rate service orchestration (cache -> provider fallback)forex.services.provider— one-frame HTTP client interpreterforex.services.cache— cache interpreters + periodic refresh jobforex.services.logging— tagless logging algebra + interpreters2) Cache-first strategy with periodic warm-up
CacheRefreshJobthat preloads all supported currency pairs every 4 minutes.forex.domain.Currencyand materialized viaRate.allPairs(...).3) Provider contract designed for batch usage
List[Rate.Pair]and returnsMap[Rate.Pair, Rate].4) API error wrapper and request validation
error_type,error_code,error_message,display_message,request_id).fromStringEither) to avoid runtimeMatchErroron unsupported input.UNSUPPORTED_CURRENCY) instead of internal failures.5) Smart and minimal logging
Logger[F]algebra and interpreters (slf4j,noop).Architectural Decisions and Trade-offs
Why in-memory Caffeine, not Redis
Given the stated traffic and freshness constraints, a local in-memory cache is the simplest reliable option.
For horizontal scale (multiple app instances), a shared cache (Redis) can be introduced later if consistency requirements tighten.
Why validate currencies against the domain list
forex.domain.Currencydefines the supported product scope.