"""Scheduler for recurring-task spawning. Every 15 minutes, creates the next occurrence of any recurring task whose spawn time has arrived — draining `recurrence_next_spawn_at`, which is armed on task completion. Without this job, recurring tasks would never recur. One ScheduledJob (services/scheduler.py), like the other *_scheduler modules. (Formerly event_scheduler.py, which also ran event reminders + CalDAV sync; those were removed when the calendar surface was retired.) """ from __future__ import annotations import asyncio import logging from apscheduler.triggers.interval import IntervalTrigger from scribe.services.scheduler import ScheduledJob logger = logging.getLogger(__name__) async def _run_recurrence_spawn() -> None: from scribe.services.recurrence import spawn_recurring_tasks # noqa: PLC0415 await spawn_recurring_tasks() _JOB = ScheduledJob("recurrence_spawn", _run_recurrence_spawn, label="Recurring-task spawn") def start_recurrence_scheduler(loop: asyncio.AbstractEventLoop) -> None: # Spawn the next occurrence of due recurring tasks every 15 minutes. # Without this job, recurrence_next_spawn_at is armed on completion but # never drained, so recurring tasks never recur. _JOB.start(loop, IntervalTrigger(minutes=15), describe="recurring-task spawn every 15m") def stop_recurrence_scheduler() -> None: _JOB.stop()