""" APScheduler setup for background cleanup jobs. One scheduler instance runs per process. Jobs run in their own threads (ThreadPoolExecutor). """ from __future__ import annotations import logging from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.executors.pool import ThreadPoolExecutor logger = logging.getLogger(__name__) _scheduler: BackgroundScheduler | None = None def get_scheduler() -> BackgroundScheduler: global _scheduler if _scheduler is None: _scheduler = BackgroundScheduler( executors={"default": ThreadPoolExecutor(max_workers=2)}, job_defaults={"coalesce": True, "max_instances": 1}, ) return _scheduler def start_scheduler() -> None: sched = get_scheduler() if not sched.running: sched.start() logger.info("APScheduler started") def stop_scheduler() -> None: global _scheduler if _scheduler is not None and _scheduler.running: _scheduler.shutdown(wait=False) logger.info("APScheduler stopped")