Files
weatherapi/docs/internal/runtime.md

3.8 KiB

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, and configuration fields belong in docs/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.

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.