"""Celery app + beat schedule.""" from celery import Celery from celery.schedules import crontab from app.core.config import settings def _parse_cron(spec: str) -> crontab: """Parse 'M H DoM Mon DoW' crontab string into Celery crontab. Empty fields default to '*'.""" parts = spec.strip().split() if len(parts) != 5: raise ValueError(f"crontab spec must have 5 fields, got: {spec!r}") minute, hour, dom, month, dow = parts return crontab( minute=minute, hour=hour, day_of_month=dom, month_of_year=month, day_of_week=dow, ) def _default_regions() -> list[int]: return [int(x.strip()) for x in settings.scrape_kn_default_regions.split(",") if x.strip()] celery_app = Celery( "gendesign", broker=settings.redis_url, backend=settings.redis_url, include=["app.workers.tasks.scrape_kn"], ) celery_app.conf.timezone = "Europe/Moscow" # Расписание задаётся через SCRAPE_KN_CRON env var (см. app.core.config). # Каждый региональный sweep оборачивается случайной задержкой 0..SCRAPE_KN_JITTER_SECONDS # внутри самой задачи (см. tasks.scrape_kn) — чтобы не бить ровно в одну минуту. celery_app.conf.beat_schedule = { f"kn-region-{rc}": { "task": "tasks.scrape_kn.scrape_kn_region", "schedule": _parse_cron(settings.scrape_kn_cron), "args": [rc, None], } for rc in _default_regions() }