feat: APScheduler entry point — 5-job weekly cadence (Pacific)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 06:46:39 -07:00
co-authored by Claude Sonnet 4.6
parent 14a0ed1ced
commit 7972ecb948
2 changed files with 68 additions and 0 deletions
View File
+68
View File
@@ -0,0 +1,68 @@
"""
APScheduler entry point for the scheduler container.
Run: python -m app.scheduler
Weekly cadence (America/Los_Angeles):
Fri 02:00 — scrape (Lucky weekend prices live by ~midnight)
Fri 05:00 — generate (fresh grocery data)
Fri 06:00 — email (per-voter approval links)
Fri 17:00 — deadline (pending items resolved per family policy)
Fri 18:00 — finalize (shopping-list email)
"""
import logging
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
from app.services.orchestrator.runner import run_step
logging.basicConfig(
level="INFO",
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger(__name__)
TZ = "America/Los_Angeles"
scheduler = BlockingScheduler(timezone=TZ)
scheduler.add_job(
lambda: run_step("scrape"),
CronTrigger(day_of_week="fri", hour=2, minute=0, timezone=TZ),
id="weekly_scrape",
name="Weekly scrape (Fri 02:00 PT)",
)
scheduler.add_job(
lambda: run_step("generate"),
CronTrigger(day_of_week="fri", hour=5, minute=0, timezone=TZ),
id="weekly_generate",
name="Weekly generate (Fri 05:00 PT)",
)
scheduler.add_job(
lambda: run_step("email"),
CronTrigger(day_of_week="fri", hour=6, minute=0, timezone=TZ),
id="weekly_email",
name="Weekly email (Fri 06:00 PT)",
)
scheduler.add_job(
lambda: run_step("deadline"),
CronTrigger(day_of_week="fri", hour=17, minute=0, timezone=TZ),
id="weekly_deadline",
name="Weekly deadline (Fri 17:00 PT)",
)
scheduler.add_job(
lambda: run_step("finalize"),
CronTrigger(day_of_week="fri", hour=18, minute=0, timezone=TZ),
id="weekly_finalize",
name="Weekly finalize (Fri 18:00 PT)",
)
if __name__ == "__main__":
logger.info("Starting MealPlanner scheduler (tz=%s)", TZ)
for job in scheduler.get_jobs():
logger.info(" Registered: %s", job.name)
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped")