You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.2 KiB
Python
74 lines
2.2 KiB
Python
"""
|
|
APScheduler-based batch scheduler for the Overlay headline collector.
|
|
|
|
Integrated into FastAPI's lifespan via start_scheduler() / stop_scheduler().
|
|
"""
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_scheduler = None
|
|
|
|
|
|
def _get_scheduler():
|
|
global _scheduler
|
|
if _scheduler is None:
|
|
try:
|
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
_scheduler = AsyncIOScheduler(timezone="UTC")
|
|
except ImportError:
|
|
logger.warning("apscheduler not installed; overlay scheduling disabled")
|
|
return None
|
|
return _scheduler
|
|
|
|
|
|
async def _run_collect_job() -> None:
|
|
"""Scheduled job: collect Yahoo RSS headlines."""
|
|
from app.core.database import AsyncSessionLocal
|
|
from app.services.overlay.overlay_pipeline import OverlayPipeline
|
|
|
|
pipeline = OverlayPipeline()
|
|
async with AsyncSessionLocal() as db:
|
|
try:
|
|
counts = await pipeline.collect_all(db)
|
|
logger.info(f"[Scheduler] collect_all completed: {counts}")
|
|
except Exception as e:
|
|
logger.error(f"[Scheduler] collect_all failed: {e}")
|
|
|
|
|
|
def start_scheduler() -> None:
|
|
"""Start the APScheduler. Call from FastAPI lifespan startup."""
|
|
from app.core.config import settings
|
|
|
|
if not getattr(settings, "OVERLAY_ENABLED", True):
|
|
logger.info("Overlay disabled; scheduler not started")
|
|
return
|
|
|
|
sched = _get_scheduler()
|
|
if sched is None:
|
|
return
|
|
|
|
try:
|
|
from apscheduler.triggers.cron import CronTrigger
|
|
|
|
# Yahoo RSS collect: 23:30 UTC daily on weekdays (≈ 18:30 ET)
|
|
sched.add_job(
|
|
_run_collect_job,
|
|
trigger=CronTrigger(day_of_week="mon-fri", hour=23, minute=30, timezone="UTC"),
|
|
id="overlay_collect",
|
|
replace_existing=True,
|
|
misfire_grace_time=600,
|
|
)
|
|
sched.start()
|
|
logger.info("Overlay scheduler started (collect @ 23:30 UTC, weekdays)")
|
|
except Exception as e:
|
|
logger.error(f"Overlay scheduler start failed: {e}")
|
|
|
|
|
|
def stop_scheduler() -> None:
|
|
sched = _get_scheduler()
|
|
if sched and sched.running:
|
|
sched.shutdown(wait=False)
|
|
logger.info("Overlay scheduler stopped")
|