From 9611a7be8bb1a61ddb92a87792639d87fdfba2c8 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Mon, 20 Jul 2026 18:26:39 -0700 Subject: [PATCH] Add a worker scheduler for city warming and IndexNow pings (#242) warm_cities.py and indexnow.py are one-shot scripts run manually at deploy today - nothing keeps the curated city set topped up, or pings IndexNow, between deploys. Add notifications/scheduler.py: an in-process APScheduler instance driving two recurring jobs (city warming, daily; IndexNow --if-changed, every 6h by default), gated by the same leader election as the notifier - only the process that already won leadership starts it, so the jobs run in exactly one place under multi-host Swarm rather than once per replica. Neither job runs immediately on start: warm_cities already runs at deploy time, so an immediate duplicate on every worker boot/restart would be wasted work. Extract indexnow.submit_if_changed() from the CLI's --if-changed branch so the scheduler and the command line share the exact same skip-when-unchanged logic instead of two copies drifting apart. The CLI's plain (non-flag) path is unchanged. APScheduler over a Postgres-native queue: exactly one process ever runs this, no fan-out/backpressure/dead-letter need, no new infrastructure. --- deploy/thermograph.env.example | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deploy/thermograph.env.example b/deploy/thermograph.env.example index 79a1106..94cb2e8 100644 --- a/deploy/thermograph.env.example +++ b/deploy/thermograph.env.example @@ -67,6 +67,12 @@ WORKERS=4 # Read once at process start; changing it needs a restart, not a live toggle. #THERMOGRAPH_ROLE=all +# The worker's own recurring jobs (city warming, IndexNow), gated by the same +# leader election as the notifier above. Hours between runs; both are cheap +# no-op skips when there's nothing to do, so the defaults rarely need changing. +#THERMOGRAPH_WARM_CITIES_INTERVAL_HOURS=24 +#THERMOGRAPH_INDEXNOW_INTERVAL_HOURS=6 + # Base path the app is served under. # / -> app at the domain root (Thermograph owns the whole domain — # this is what the Caddyfile expects: thermograph.org proxies "/")