docs: improve docs
This commit is contained in:
36
README.md
36
README.md
@@ -70,19 +70,39 @@ Example response:
|
|||||||
|
|
||||||
`/pokemon/translated/{name}` applies Yoda when the Pokémon is legendary or its habitat is `cave`; otherwise it applies Shakespeare. If translation fails or returns an empty result, the API falls back to the standard PokéAPI description.
|
`/pokemon/translated/{name}` applies Yoda when the Pokémon is legendary or its habitat is `cave`; otherwise it applies Shakespeare. If translation fails or returns an empty result, the API falls back to the standard PokéAPI description.
|
||||||
|
|
||||||
## Architecture
|
# Architecture
|
||||||
|
|
||||||
|
This is a small Rust service, so the structure is intentionally a lightweight hexagonal/onion layout rather than a framework-heavy one.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
CLI[CLI helper] --> HTTP[HTTP layer]
|
CLI[CLI helper] --> HTTP
|
||||||
HTTP --> APP[Application service]
|
HTTP[HTTP layer: axum routes, handlers, middleware] --> Application
|
||||||
APP --> DOMAIN[Domain]
|
Application[Application service: use cases and translation rules] --> Domain
|
||||||
APP --> CLIENTS[External clients]
|
Application --> Clients
|
||||||
HTTP --> OTEL[Telemetry]
|
Clients[External clients: PokéAPI and FunTranslations]
|
||||||
APP --> OTEL
|
HTTP --> Telemetry
|
||||||
|
Application --> Telemetry
|
||||||
```
|
```
|
||||||
|
|
||||||
See `docs/architecture.md` for the design notes.
|
## Layers
|
||||||
|
|
||||||
|
- `domain`: core data and business concepts (`PokemonInfo`, `TranslationKind`).
|
||||||
|
- `application`: orchestration and business rules, including Yoda vs Shakespeare selection and fallback behavior.
|
||||||
|
- `clients`: adapters for external providers (`PokéAPI`, `FunTranslations`).
|
||||||
|
- `http`: API transport concerns, routing, handlers, request IDs, metrics middleware, and rate limiting.
|
||||||
|
- `telemetry`: OpenTelemetry metrics and tracing setup.
|
||||||
|
- `bin`: executable entrypoints for the API and the local CLI helper.
|
||||||
|
|
||||||
|
## Deliberate trade-offs
|
||||||
|
|
||||||
|
The application service currently depends on concrete clients instead of trait-based ports. For this challenge that keeps the code easier to read and avoids abstractions that do not buy much yet. In a larger enterprise codebase, those clients would likely become traits owned by the application layer, with HTTP clients as adapters, so providers could be swapped or mocked without depending on concrete implementations.
|
||||||
|
|
||||||
|
PokéAPI species data changes rarely, so production deployments would add a bounded LRU cache with TTL for successful species responses. That would avoid unnecessary random upstream hits, reduce latency, and make transient provider failures less visible to users.
|
||||||
|
|
||||||
|
Rate limiting is intentionally simple and in-memory. In production, this should usually live in an API gateway or shared rate-limiting service so limits are consistent across instances and can be keyed by API key, user, or client IP.
|
||||||
|
|
||||||
|
External contract tests are separated from the normal deterministic test suite. Unit and integration tests use mocks; the nightly workflow calls real providers to detect contract drift early.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
# Architecture
|
|
||||||
|
|
||||||
This is a small Rust service, so the structure is intentionally a lightweight hexagonal/onion layout rather than a framework-heavy one.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart LR
|
|
||||||
CLI[CLI helper] --> HTTP
|
|
||||||
HTTP[HTTP layer: axum routes, handlers, middleware] --> Application
|
|
||||||
Application[Application service: use cases and translation rules] --> Domain
|
|
||||||
Application --> Clients
|
|
||||||
Clients[External clients: PokéAPI and FunTranslations]
|
|
||||||
HTTP --> Telemetry
|
|
||||||
Application --> Telemetry
|
|
||||||
```
|
|
||||||
|
|
||||||
## Layers
|
|
||||||
|
|
||||||
- `domain`: core data and business concepts (`PokemonInfo`, `TranslationKind`).
|
|
||||||
- `application`: orchestration and business rules, including Yoda vs Shakespeare selection and fallback behavior.
|
|
||||||
- `clients`: adapters for external providers (`PokéAPI`, `FunTranslations`).
|
|
||||||
- `http`: API transport concerns, routing, handlers, request IDs, metrics middleware, and rate limiting.
|
|
||||||
- `telemetry`: OpenTelemetry metrics and tracing setup.
|
|
||||||
- `bin`: executable entrypoints for the API and the local CLI helper.
|
|
||||||
|
|
||||||
## Deliberate trade-offs
|
|
||||||
|
|
||||||
The application service currently depends on concrete clients instead of trait-based ports. For this challenge that keeps the code easier to read and avoids abstractions that do not buy much yet. In a larger enterprise codebase, those clients would likely become traits owned by the application layer, with HTTP clients as adapters, so providers could be swapped or mocked without depending on concrete implementations.
|
|
||||||
|
|
||||||
PokéAPI species data changes rarely, so production deployments would add a bounded LRU cache with TTL for successful species responses. That would avoid unnecessary random upstream hits, reduce latency, and make transient provider failures less visible to users.
|
|
||||||
|
|
||||||
Rate limiting is intentionally simple and in-memory. In production, this should usually live in an API gateway or shared rate-limiting service so limits are consistent across instances and can be keyed by API key, user, or client IP.
|
|
||||||
|
|
||||||
External contract tests are separated from the normal deterministic test suite. Unit and integration tests use mocks; the nightly workflow calls real providers to detect contract drift early.
|
|
||||||
Reference in New Issue
Block a user