"""arq worker entrypoint (SPEC §2 ``workers/worker.py``). Run with: ``arq workers.worker.WorkerSettings`` (from ``backend/``). """ from __future__ import annotations import logging import uuid from typing import Any from app.config import get_settings from app.outbox.draft_sync import push_draft_to_imap_job, remove_imap_draft_job from app.outbox.jobs import send_job from app.queue import redis_settings as arq_redis_settings from app.sync.actions import ( delete_thread_job, move_job, move_thread_to_folder_job, push_flags_job, ) from app.sync.engine import bootstrap_and_backfill, refresh_account_job logger = logging.getLogger(__name__) async def sync_bootstrap_account(ctx: dict[str, Any], account_id: str) -> int: """Bootstrap + backfill an account (enqueued on account creation).""" logger.info("sync.bootstrap_account start account=%s", account_id) count = await bootstrap_and_backfill(uuid.UUID(account_id)) logger.info("sync.bootstrap_account done account=%s messages=%d", account_id, count) return count async def on_startup(ctx: dict[str, Any]) -> None: logging.basicConfig(level=get_settings().log_level) from app.sync.supervisor import start_supervisor await start_supervisor(ctx) logger.info("webmail worker started") async def on_shutdown(ctx: dict[str, Any]) -> None: from app.db import dispose_engine from app.redis_client import close_redis from app.sync.supervisor import stop_supervisor await stop_supervisor(ctx) await dispose_engine() await close_redis() logger.info("webmail worker stopped") class WorkerSettings: """arq worker configuration.""" functions = [ sync_bootstrap_account, push_flags_job, move_job, move_thread_to_folder_job, delete_thread_job, send_job, push_draft_to_imap_job, remove_imap_draft_job, refresh_account_job, ] on_startup = on_startup on_shutdown = on_shutdown max_jobs = 10 # global worker cap (SPEC §6.3) job_timeout = 3600 # backfill of a large account can be long redis_settings = arq_redis_settings()