Add internal architecture documentation

This commit is contained in:
2026-06-11 14:19:51 +00:00
parent ec027e34cc
commit 9fe480d3ab
4 changed files with 556 additions and 0 deletions

105
docs/internal/runtime.md Normal file
View File

@@ -0,0 +1,105 @@
# Runtime Composition
This document describes how the `weatherapi` executable wires configuration,
database handles, application services, HTTP endpoints, renderers, and shutdown.
It is development-facing; operator commands belong in
[`docs/operations.md`](../operations.md), and configuration fields belong in
[`docs/config.md`](../config.md).
## Purpose
`cmd/weatherapi/main.go` is the composition root. It should stay thin and only
connect already-implemented packages. Endpoint logic, SQL, presentation logic,
and business read behavior belong outside `cmd`.
## Inputs and Outputs
Inputs:
- config path from `-config`, `WEATHERAPI_CONFIG`, or `config.yml`;
- feedapi YAML config containing `server`, `databases`, and `templates`;
- OS cancellation signals;
- database handles opened by feedapi.
Outputs:
- a configured feedapi HTTP server;
- registered `weatherapi` endpoint definitions;
- process logs for fatal startup errors and database close errors.
## Composition Flow
The executable:
1. sets standard logger flags with microsecond precision;
2. resolves the config path;
3. creates a context canceled by `os.Interrupt` or `SIGTERM`;
4. loads config with `feedapi/config.Load`;
5. requires at least one configured database;
6. opens all configured databases with `feedapi/db.OpenAll`;
7. selects the first configured database name as the primary store;
8. constructs `postgres.Repository` with the primary `*sql.DB`;
9. constructs `app.Service` over the repository;
10. builds HTTP endpoint definitions with `httpapi.Definitions`;
11. constructs a feedapi app with the DB registry and endpoints;
12. starts feedapi with the signal-aware context.
## Config Fields Used
Runtime composition uses:
- `server`: consumed by feedapi for HTTP runtime settings and default format;
- `databases`: opened by feedapi, with the first entry selected as primary;
- `templates`: consumed by feedapi for text-template loading.
Do not duplicate the config field reference here. Keep it in
[`docs/config.md`](../config.md).
## External Adapters Used
- `feedapi/config`: YAML loading.
- `feedapi/db`: database registry and lifecycle.
- `feedapi/app`: HTTP runtime construction and startup.
- `internal/adapters/outbound/postgres`: weather read repository.
- `internal/adapters/inbound/httpapi`: endpoint definition registry.
- `github.com/lib/pq`: Postgres driver registration through blank import.
## State and Lifecycle
`weatherapi` owns no durable weather state. Runtime state is limited to loaded
configuration, database pools, endpoint definitions, renderer/template
registries managed by feedapi, and the running HTTP server.
Database handles are closed with a deferred registry close. Close errors are
logged but do not change response behavior because they occur during shutdown.
## Failure Behavior
`run` wraps startup errors with operation context:
- `load config`
- `config.databases requires at least one entry`
- `open databases`
- `select primary database`
- `build app`
Errors returned by `a.Start(ctx)` are returned to `main`, which logs a fatal
`weatherapi failed: ...` message. Feedapi owns graceful HTTP shutdown after the
context is canceled.
## Tests to Inspect Before Changing
- `internal/app/service_test.go` for service wiring expectations.
- `internal/adapters/inbound/httpapi/endpoints_test.go` for endpoint registry
and runtime adapter expectations.
- Full `go test ./...` when runtime wiring, config behavior, or feedapi
integration changes.
## Invariants
- Keep `cmd/weatherapi` as composition code only.
- Preserve config path precedence: `-config`, `WEATHERAPI_CONFIG`, `config.yml`.
- Preserve first configured database as the primary weather store.
- Keep generic HTTP runtime behavior in feedapi.
- Keep endpoint definitions in the HTTP adapter.
- Keep SQL and row mapping in the Postgres adapter.