| import logging
|
|
|
| from celery import Celery
|
| from celery.signals import worker_process_init
|
|
|
| from app.core.config import settings
|
|
|
| logger = logging.getLogger(__name__)
|
|
|
| celery_app = Celery(
|
| "hair_portfolio",
|
| broker=settings.celery_broker_url,
|
| backend=settings.celery_result_backend,
|
| )
|
|
|
| celery_app.conf.update(
|
| task_serializer="json",
|
| result_serializer="json",
|
| accept_content=["json"],
|
| task_track_started=True,
|
| task_acks_late=True,
|
| worker_prefetch_multiplier=1,
|
| task_time_limit=300,
|
| task_soft_time_limit=240,
|
| task_always_eager=settings.celery_task_always_eager,
|
| task_eager_propagates=settings.celery_task_eager_propagates,
|
| )
|
|
|
| @worker_process_init.connect
|
| def _preload_local_models(**_kwargs) -> None:
|
| """On real worker boot (not eager/tests), pre-load the local face model for the
|
| falinpaint provider so the first customer doesn't pay the ~8s load. Failure-safe;
|
| only fires for an actual worker process. (faceswap loads its own per-instance
|
| models, so it is intentionally not pre-warmed here.)"""
|
| if settings.ai_provider not in {"falinpaint", "nanobanana_fal", "kontext_composite", "hybrid"}:
|
| return
|
| from app.services.falinpaint_beautify import preload_face_model
|
|
|
| status = preload_face_model()
|
| logger.info("face model preload (worker boot): %s", status)
|
|
|
|
|
|
|
| celery_app.autodiscover_tasks(["app.workers"])
|
|
|
| import app.workers.tasks
|
|
|