A FizzBuzz generator exposed over HTTP, with a built-in tracking system that records which parameter combinations are called most frequently.
GET /api/v1/fizzbuzz— generates a FizzBuzz sequence for any divisors, limit, and custom stringsGET /api/v1/stats/— returns the most frequently requested parameter combination and its hit countGET /health— health check
The project is split into three modules:
fizzbuzz— pure stateless logic, no I/Otracker— request tracking via SQLite, completely decoupled from fizzbuzzapi— FastAPI app wiring both modules together
Tracking is applied via a @track_request decorator on the router handler. This keeps the fizzbuzz logic clean and the tracking concern isolated — adding or removing tracking doesn't touch the business logic.
| Param | Type | Constraint | Description |
|---|---|---|---|
int1 |
int | > 0 |
First divisor |
int2 |
int | > 0 |
Second divisor |
limit |
int | > 0, ≤ 10000 |
Sequence length |
str1 |
str | required | String for multiples of int1 |
str2 |
str | required | String for multiples of int2 |
Example:
GET /api/v1/fizzbuzz?int1=3&int2=5&limit=15&str1=Fizz&str2=Buzz
{
"result": ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz"]
}Returns the most frequently requested parameter combination.
{
"hits": 42,
"requests": [
{ "int1": 3, "int2": 5, "limit": 15, "str1": "Fizz", "str2": "Buzz" }
]
}Returns {} if no requests have been made yet.
Decorator-based tracking — @track_request inspects the function signature at call time and serializes params to JSON before persisting. The fizzbuzz router has no awareness of the tracking layer.
SQLite with WAL mode — lightweight, no infrastructure needed. WAL journal mode + synchronous=NORMAL gives a good balance between write performance and crash safety.
Validation at the router layer — FastAPI query constraints (gt=0, le=10000) reject invalid input before it reaches the service. The service stays pure.
Dev/prod distinction — ENV=dev enables uvicorn hot-reload by passing the app as an import string. Production passes the app object directly.
uv sync
uv run fizzbuzzWith hot-reload:
ENV=dev uv run fizzbuzzdocker compose upRuns with ENV=dev (hot-reload enabled), persists the SQLite DB in ./data, and reflects code changes without rebuilding.
uv sync --all-groups
uv run pytestEach test runs against an isolated SQLite database per test — no shared state between tests.
GitHub Actions runs on every push and pull request to main:
- Lint —
ruff check+ruff format --check - Test —
pytest
- Async SQLAlchemy (
AsyncSession+aiosqlite) to avoid blocking the event loop on DB writes - Auth on the stats endpoint
- Proper migrations (Alembic)
- Rate limiting