Thermograph monorepo: graded-climate API + SSR frontend + infra, domain-specific containerized deploys
* Add a Postgres advisory-lock leader election for multi-host deploys The subscription notifier elects one leader via a host-local flock (THERMOGRAPH_SINGLETON_LOCK) so multiple uvicorn workers on one host don't each run it. Under multi-host Swarm that guard is insufficient: each host would independently elect its own leader, multiplying Open-Meteo quota use N-fold again. Add claim_pg(key) alongside the existing claim(lock_path): a cluster-wide Postgres advisory lock, visible to every host talking to the same database. The holding connection is dedicated and kept for the process lifetime (advisory locks are session-scoped); a dead connection is dropped and re-election retried on the next call. claim_leader() dispatches between the two mechanisms from env: THERMOGRAPH_SINGLETON_PG (+ Postgres) -> claim_pg; else THERMOGRAPH_SINGLETON_LOCK -> claim; else always leader, unchanged. Wired in at web/app.py in place of the direct claim() call. Off by default, so today's single-host behavior is unaffected. * Split web/worker duties with THERMOGRAPH_ROLE Background work (the subscription notifier) is welded to the same process that serves requests, so scaling the web tier to N replicas would also scale notifier instances unless something restricts it further than leader election alone. Add THERMOGRAPH_ROLE (web|worker|all, default all - unchanged single-process behavior). Every replica runs the same image; ROLE only gates whether a process is allowed to own the notifier at all, layered on top of the existing leader election: web replicas never start it even if they'd win leader election, worker replicas start it if they win. The decision is pulled into _should_run_notifier() so it's unit-testable without booting the full app (DB init, places index, neighbor warmer). Add a minimal /healthz liveness route (no DB/upstream I/O, not under BASE) so a worker replica - which serves no real traffic - still has something Swarm can health-check. * Retrigger CI (no prior check run was ever recorded for this PR) |
||
|---|---|---|
| content | ||
| static | ||