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.
27 lines
1.1 KiB
Text
27 lines
1.1 KiB
Text
fastapi==0.115.6
|
|
uvicorn[standard]==0.34.0
|
|
httpx==0.28.1
|
|
polars==1.42.1
|
|
numpy==2.2.1
|
|
# Accounts + notification subscriptions (see accounts/db.py, users.py, notify.py).
|
|
# Postgres in prod/containers: asyncpg (async web/store) + psycopg (sync notifier);
|
|
# aiosqlite is kept for the SQLite fallback the test suite runs on. alembic manages
|
|
# the accounts schema.
|
|
fastapi-users[sqlalchemy]==15.0.5
|
|
aiosqlite==0.22.1
|
|
asyncpg==0.30.0
|
|
psycopg[binary]==3.2.3
|
|
alembic==1.14.0
|
|
# Web Push (VAPID) delivery of notifications (see backend/push.py). Pulls in
|
|
# py-vapid, cryptography, and http-ece.
|
|
pywebpush==2.0.0
|
|
# Ed25519 verification of Discord interaction webhooks (see backend/discord_interactions.py).
|
|
PyNaCl==1.5.0
|
|
# Server-rendered SEO content pages (see backend/web/content.py, templates/).
|
|
jinja2==3.1.6
|
|
# Structured SSR copy (glossary, static-page SEO meta) — see
|
|
# backend/web/content_loader.py and content/.
|
|
PyYAML==6.0.3
|
|
# Recurring worker-tier jobs — city warming, IndexNow pings (see
|
|
# notifications/scheduler.py). In-process; no broker/queue needed at this scale.
|
|
apscheduler==3.11.3
|