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.
This commit is contained in:
Emi Griffith 2026-07-20 18:26:39 -07:00 committed by GitHub
parent e5137e777d
commit 9611a7be8b

View file

@ -67,6 +67,12 @@ WORKERS=4
# Read once at process start; changing it needs a restart, not a live toggle. # Read once at process start; changing it needs a restart, not a live toggle.
#THERMOGRAPH_ROLE=all #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. # Base path the app is served under.
# / -> app at the domain root (Thermograph owns the whole domain — # / -> app at the domain root (Thermograph owns the whole domain —
# this is what the Caddyfile expects: thermograph.org proxies "/") # this is what the Caddyfile expects: thermograph.org proxies "/")