"""Scheduled jobs — generic framework for periodic background work. Replaces the ad-hoc ``asyncio.sleep`` loops and scattered APScheduler cron registrations that lived in ``app/worker.py``. Every recurring job (HRIS incremental sync, overdue-leaver check, domain-expiry alert, future "daily leaver reminder push", …) is now a row in the ``scheduled_jobs`` table with: - ``handler_key`` pointing at a function registered via :func:`register_scheduled_job` — the only code actually doing work. - ``trigger_type`` + ``cron_expr`` / ``interval_seconds`` that drive APScheduler at worker boot. - ``enabled``, ``last_run_*`` metrics, and ``config`` (JSON) so IT admin can pause a job, change its cadence, or tweak a parameter without touching code. Adding a new recurring task is: @register_scheduled_job(key="foo.bar", display_name="...", description="...") async def _run(db, config): ... # … then INSERT one row into scheduled_jobs (or let migration/seed do it). The admin console at ``/admin/scheduled-jobs`` reflects whatever is in the table and records every run in ``scheduled_job_runs``. """ from app.scheduled_jobs.registry import ( # noqa: F401 SchedJobHandler, get_handler, list_handlers, register_scheduled_job, )