#!/usr/bin/env python3 """Scheduler loop for the news summarizer — every NEWS_SUMMARIZE_INTERVAL_S. Default 900s (15 minutes). Serial: a slow LLM pass never overlaps the next. Env (all optional, 12-factor): NEWS_SUMMARIZE_INTERVAL_S seconds between runs (default 900) NEWS_SUMMARIZE_RUN_ON_START "1" to summarize once immediately on boot (default 1) NOUS_API_KEY optional in env; Keys UI / api_keys also works """ from __future__ import annotations import datetime import logging import os import subprocess import sys import time logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s") logger = logging.getLogger("news.summarizer.scheduler") INTERVAL_S = max(1, int(os.getenv("NEWS_SUMMARIZE_INTERVAL_S", "900"))) RUN_ON_START = os.getenv("NEWS_SUMMARIZE_RUN_ON_START", "1").lower() in ("1", "true", "yes") def run_summarize() -> None: logger.info("summarize starting at %s", datetime.datetime.now().isoformat(timespec="seconds")) try: proc = subprocess.run([sys.executable, "summarizer.py"], cwd="/app") logger.info("summarize finished rc=%s", proc.returncode) except Exception: # noqa: BLE001 — keep the loop alive across failures logger.exception("summarize failed") def main() -> None: if not os.getenv("NOUS_API_KEY", "").strip(): logger.warning( "NOUS_API_KEY unset in env — will read api_keys on each run; idle if both empty" ) logger.info( "news summarizer loop starting (interval_s=%s, run_on_start=%s)", INTERVAL_S, RUN_ON_START, ) if RUN_ON_START: run_summarize() while True: logger.info("next summarize in %ss", INTERVAL_S) time.sleep(INTERVAL_S) run_summarize() if __name__ == "__main__": sys.exit(main())