# 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.