6.6 KiB
weatherapi Operations
weatherapi is a read-only HTTP service. It serves latest weather records from
Postgres tables populated by weatherfeeder; it does not ingest provider data,
create tables, or run database migrations.
Runtime Model
At startup, the executable:
- resolves the config path from
-config,WEATHERAPI_CONFIG, orconfig.yml; - loads feedapi YAML configuration;
- opens all configured database handles;
- selects the first configured database as the primary weather data store;
- registers HTTP endpoints and text templates with feedapi;
- starts the HTTP server.
See docs/cli.md for invocation details and docs/config.md
for configuration fields.
Prerequisites
- A reachable PostgreSQL database.
- Weatherfeeder-owned weather tables already created and populated.
- A config file with at least one
databasesentry. - The
templates/directory whenformat=textresponses are needed. - Network access from the service process or container to Postgres.
The first database entry in the config is the only database used for weather
reads. Additional configured handles may be opened by feedapi, but weatherapi
selects the first entry as primary.
Local Run
Use the checked-in local sample only when its database settings match your environment:
go run ./cmd/weatherapi -config config.yml
For a local binary:
go build -o ./weatherapi ./cmd/weatherapi
./weatherapi -config config.yml
Keep the process working directory aligned with templates.base_dir. With the
checked-in config, run from the repository root so templates resolves to the
repository's template directory.
Container Run
The Docker image copies these runtime files into /weatherapi:
/weatherapi/weatherapi/weatherapi/config.yml/weatherapi/templates
The runtime working directory is /weatherapi, and the entrypoint is the
weatherapi binary. To use the image's bundled config and templates:
docker run --rm -p 8080:8080 weatherapi
To provide an external config file:
docker run --rm -p 8080:8080 \
-v "$PWD/examples/config.production.yml:/weatherapi/config.yml:ro" \
weatherapi
To use a different config path, append the CLI flag:
docker run --rm -p 8080:8080 \
-v "$PWD/config.yml:/config/weatherapi.yml:ro" \
weatherapi -config /config/weatherapi.yml
If you mount a custom template directory, make templates.base_dir point to the
mounted path.
The repository's Woodpecker image build uses Kaniko and passes private Gitea credentials as build arguments so Go can download private modules during the build.
Database Dependency
weatherapi expects weatherfeeder-compatible tables for observations, current
conditions aggregation, active alerts, forecasts, forecast discussions, weather
stories, and convective outlooks. It only reads those tables.
Convective outlook endpoints require weatherfeeder's weather.outlook.v2 table
shape, including outlook_runs, outlooks, and outlook_discussions. If
operators reset or recreate outlook tables during a weatherfeeder upgrade,
complete that weatherfeeder-side migration before starting weatherapi.
Operational ownership is split:
weatherfeederowns provider polling, normalization, writes, table creation, and schema compatibility.- PostgreSQL owns durable storage, backups, replication, and restore.
weatherapiowns serving read-only HTTP responses from the configured primary database.
When restoring from backup or replacing the database, verify that weatherfeeder
has resumed writes before treating stale weatherapi responses as an API
problem.
Templates and Text Output
JSON and XML responses do not depend on text templates. format=text uses the
template named by each endpoint, with templates stored under templates.base_dir.
The repository includes templates for all implemented endpoint families: observations, current conditions, active alerts, hourly forecasts, narrative forecasts, forecast discussions, weather stories, and convective outlooks.
If text rendering fails or returns an unsupported-format error, verify:
- the process can read
templates.base_dir; - expected
*.txt.tmplfiles are present; - the requested endpoint supports
format=text, which all implemented endpoints currently do.
Startup and Shutdown
Startup failures are fatal and are logged with the prefix weatherapi failed.
Common failure contexts include:
load configconfig.databases requires at least one entryopen databasesselect primary databasebuild app
The process handles SIGINT and SIGTERM. Feedapi performs graceful HTTP
shutdown after the runtime context is canceled. Database close errors during
shutdown are logged, but they occur after the service has already begun stopping.
Verification
There is no dedicated health endpoint in weatherapi. Use an implemented read
endpoint as a practical service check:
curl -i 'http://localhost:8080/observations?format=json'
Interpretation:
200 OKwith{"data": null}means the service is running but no latest observation is available.200 OKwith a populateddataobject means the service and that read path are working.400 Bad Requestindicates request validation, not service health.406 Not Acceptableindicates format negotiation.5xxindicates a runtime, database, or handler failure.
For a broader smoke check, use the requests in
examples/requests.http.
Logs
The executable uses Go's standard logger with date, time, and microseconds. Startup and fatal runtime errors are written to standard error. Container platforms should collect stdout and stderr from the process.
Backup and Recovery Boundaries
Back up and restore PostgreSQL using normal database procedures. weatherapi
has no local durable weather state to back up.
After a database restore or failover:
- confirm the configured database is reachable from the service;
- confirm weatherfeeder-owned tables exist;
- confirm weatherfeeder is writing fresh rows if current data is expected;
- restart
weatherapiif database connection settings changed; - verify with an implemented endpoint such as
/observations.
Related Docs
docs/api.md: HTTP contract and error envelopedocs/config.md: configuration referencedocs/troubleshooting.md: symptom-oriented fixesdocs/integrations/feedapi.md: runtime and rendering contractsdocs/integrations/weatherfeeder-postgres.md: storage contract assumptions