# app/celery_app.py """ Celery application configuration for Syndarix. This module configures the Celery app for background task processing: - Agent execution tasks (LLM calls, tool execution) - Git operations (clone, commit, push, PR creation) - Issue synchronization with external trackers - Workflow state management - Cost tracking and budget monitoring Architecture: - Redis as message broker and result backend - Queue routing for task isolation - JSON serialization for cross-language compatibility - Beat scheduler for periodic tasks """ from celery import Celery from app.core.config import settings # Create Celery application instance celery_app = Celery( "syndarix", broker=settings.celery_broker_url, backend=settings.celery_result_backend, ) # Define task queues with their own exchanges and routing keys TASK_QUEUES = { "agent": {"exchange": "agent", "routing_key": "agent"}, "git": {"exchange": "git", "routing_key": "git"}, "sync": {"exchange": "sync", "routing_key": "sync"}, "default": {"exchange": "default", "routing_key": "default"}, } # Configure Celery celery_app.conf.update( # Serialization task_serializer="json", accept_content=["json"], result_serializer="json", # Timezone timezone="UTC", enable_utc=True, # Task imports for auto-discovery imports=("app.tasks",), # Default queue task_default_queue="default", # Task queues configuration task_queues=TASK_QUEUES, # Task routing - route tasks to appropriate queues task_routes={ "app.tasks.agent.*": {"queue": "agent"}, "app.tasks.git.*": {"queue": "git"}, "app.tasks.sync.*": {"queue": "sync"}, "app.tasks.*": {"queue": "default"}, }, # Time limits per ADR-003 task_soft_time_limit=300, # 5 minutes soft limit task_time_limit=600, # 10 minutes hard limit # Result expiration - 24 hours result_expires=86400, # Broker connection retry broker_connection_retry_on_startup=True, # Retry configuration per ADR-003 (built-in retry with backoff) task_autoretry_for=(Exception,), # Retry on all exceptions task_retry_kwargs={"max_retries": 3, "countdown": 5}, # Initial 5s delay task_retry_backoff=True, # Enable exponential backoff task_retry_backoff_max=600, # Max 10 minutes between retries task_retry_jitter=True, # Add jitter to prevent thundering herd # Beat schedule for periodic tasks beat_schedule={ # Cost aggregation every hour per ADR-012 "aggregate-daily-costs": { "task": "app.tasks.cost.aggregate_daily_costs", "schedule": 3600.0, # 1 hour in seconds }, # Reset daily budget counters at midnight UTC "reset-daily-budget-counters": { "task": "app.tasks.cost.reset_daily_budget_counters", "schedule": 86400.0, # 24 hours in seconds }, # Check for stale workflows every 5 minutes "recover-stale-workflows": { "task": "app.tasks.workflow.recover_stale_workflows", "schedule": 300.0, # 5 minutes in seconds }, # Incremental issue sync every minute per ADR-011 "sync-issues-incremental": { "task": "app.tasks.sync.sync_issues_incremental", "schedule": 60.0, # 1 minute in seconds }, # Full issue reconciliation every 15 minutes per ADR-011 "sync-issues-full": { "task": "app.tasks.sync.sync_issues_full", "schedule": 900.0, # 15 minutes in seconds }, }, # Task execution settings task_acks_late=True, # Acknowledge tasks after execution task_reject_on_worker_lost=True, # Reject tasks if worker dies worker_prefetch_multiplier=1, # Fair task distribution ) # Auto-discover tasks from task modules celery_app.autodiscover_tasks( [ "app.tasks.agent", "app.tasks.git", "app.tasks.sync", "app.tasks.workflow", "app.tasks.cost", ] )