import gc import ssl from celery import Celery from celery.signals import task_postrun from app.core.config import settings _use_ssl = settings.ENVIRONMENT != "local" _scheme = "rediss" if _use_ssl else "redis" _redis_url = f"{_scheme}://{settings.REDIS_HOST}:{settings.REDIS_PORT}/0" _ssl_opts = {"ssl_cert_reqs": ssl.CERT_NONE} if _use_ssl else None celery_app = Celery( "fansifter_clipper_tasks", broker=_redis_url, backend=_redis_url, ) celery_app.conf.update( broker_use_ssl=_ssl_opts, redis_backend_use_ssl=_ssl_opts, task_serializer="json", accept_content=["json"], result_serializer="json", timezone="UTC", enable_utc=True, task_track_started=True, result_expires=3600, # Timeouts — video processing can take 20-30 min for a full clip run task_time_limit=2700, # 45 min hard kill (SIGKILL) task_soft_time_limit=2400, # 40 min soft kill (raises SoftTimeLimitExceeded) # Memory management # Restart the worker process after each task so OpenCV / MediaPipe / NumPy # buffers are freed at the OS level. The startup cost (~1-2s to reload # MediaPipe models) is acceptable for tasks that run for minutes. worker_max_tasks_per_child=1, # Hard memory ceiling: kill & replace the worker if RSS exceeds 6 GB. # Frame-by-frame processing of a 4K source can peak at 3-4 GB; this # leaves headroom while preventing runaway OOM situations. worker_max_memory_per_child=6_291_456, # 6 GB in KB # Never pre-fetch more than one task — keeps a second heavy job from # piling up in the same worker while the first is still running. worker_prefetch_multiplier=1, # Reliability — only acknowledge after the task finishes so a crashed # worker doesn't silently drop a clip generation job. task_acks_late=True, task_reject_on_worker_lost=True, ) @task_postrun.connect def task_postrun_handler(sender=None, **kwargs): """Explicit GC pass after each task, before worker_max_tasks_per_child recycles the process.""" gc.collect() # Import tasks to register them with Celery # This must be done after celery_app is created from app.tasks import social_analysis, video_processing # noqa: E402, F401