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

1. resolves the config path from `-config`, `WEATHERAPI_CONFIG`, or `config.yml`;
2. loads feedapi YAML configuration;
3. opens all configured database handles;
4. selects the first configured database as the primary weather data store;
5. registers HTTP endpoints and text templates with feedapi;
6. starts the HTTP server.

See [`docs/cli.md`](cli.md) for invocation details and [`docs/config.md`](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 `databases` entry.
- The `templates/` directory when `format=text` responses 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:

```sh
go run ./cmd/weatherapi -config config.yml
```

For a local binary:

```sh
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:

```sh
docker run --rm -p 8080:8080 weatherapi
```

To provide an external config file:

```sh
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:

```sh
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, and
weather stories. It only reads those tables.

Operational ownership is split:

- `weatherfeeder` owns provider polling, normalization, writes, table creation,
  and schema compatibility.
- PostgreSQL owns durable storage, backups, replication, and restore.
- `weatherapi` owns 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, and weather stories.

If text rendering fails or returns an unsupported-format error, verify:

- the process can read `templates.base_dir`;
- expected `*.txt.tmpl` files 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 config`
- `config.databases requires at least one entry`
- `open databases`
- `select primary database`
- `build 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:

```sh
curl -i 'http://localhost:8080/observations?format=json'
```

Interpretation:

- `200 OK` with `{"data": null}` means the service is running but no latest
  observation is available.
- `200 OK` with a populated `data` object means the service and that read path
  are working.
- `400 Bad Request` indicates request validation, not service health.
- `406 Not Acceptable` indicates format negotiation.
- `5xx` indicates a runtime, database, or handler failure.

For a broader smoke check, use the requests in
[`examples/requests.http`](../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:

1. confirm the configured database is reachable from the service;
2. confirm weatherfeeder-owned tables exist;
3. confirm weatherfeeder is writing fresh rows if current data is expected;
4. restart `weatherapi` if database connection settings changed;
5. verify with an implemented endpoint such as `/observations`.

## Related Docs

- [`docs/api.md`](api.md): HTTP contract and error envelope
- [`docs/config.md`](config.md): configuration reference
- [`docs/troubleshooting.md`](troubleshooting.md): symptom-oriented fixes
- [`docs/integrations/feedapi.md`](integrations/feedapi.md): runtime and rendering contracts
- [`docs/integrations/weatherfeeder-postgres.md`](integrations/weatherfeeder-postgres.md): storage contract assumptions
