diff --git a/README.md b/README.md index 2f53a996..95d8d737 100644 --- a/README.md +++ b/README.md @@ -226,8 +226,8 @@ REDIS_PORT=6379 REDIS_DB=1 # Celery (Using Redis as broker) -BROKER_URL=redis://127.0.0.1:6379/0 -RESULT_BACKEND=redis://127.0.0.1:6379/0 +REDIS_DB_CELERY_BROKER=1 +REDIS_DB_CELERY_BACKEND=2 # JWT Secret Key (Formation method: openssl rand -hex 32) SECRET_KEY=your-secret-key-here diff --git a/README_CN.md b/README_CN.md index aed69b03..1472acac 100644 --- a/README_CN.md +++ b/README_CN.md @@ -201,8 +201,8 @@ REDIS_PORT=6379 REDIS_DB=1 # Celery (使用Redis作为broker) -BROKER_URL=redis://127.0.0.1:6379/0 -RESULT_BACKEND=redis://127.0.0.1:6379/0 +REDIS_DB_CELERY_BROKER=1 +REDIS_DB_CELERY_BACKEND=2 # JWT密钥 (生成方式: openssl rand -hex 32) SECRET_KEY=your-secret-key-here diff --git a/api/app/celery_app.py b/api/app/celery_app.py index 863fc21c..0319e079 100644 --- a/api/app/celery_app.py +++ b/api/app/celery_app.py @@ -1,27 +1,54 @@ import os import platform from datetime import timedelta -from celery.schedules import crontab from urllib.parse import quote from celery import Celery from celery.schedules import crontab from app.core.config import settings +from app.core.logging_config import get_logger + +logger = get_logger(__name__) # macOS fork() safety - must be set before any Celery initialization if platform.system() == 'Darwin': os.environ.setdefault('OBJC_DISABLE_INITIALIZE_FORK_SAFETY', 'YES') # 创建 Celery 应用实例 -# broker: 任务队列(使用 Redis DB 0) -# backend: 结果存储(使用 Redis DB 10) +# broker: 任务队列(使用 Redis DB,由 CELERY_BROKER_DB 指定) +# backend: 结果存储(使用 Redis DB,由 CELERY_BACKEND_DB 指定) +# NOTE: 不要在 .env 中设置 BROKER_URL / RESULT_BACKEND / CELERY_BROKER / CELERY_BACKEND, +# 这些名称会被 Celery CLI 的 Click 框架劫持,详见 docs/celery-env-bug-report.md + +# Build canonical broker/backend URLs and force them into os.environ so that +# Celery's Settings.broker_url property (which checks CELERY_BROKER_URL first) +# cannot be overridden by stray env vars. +# See: https://github.com/celery/celery/issues/4284 +_broker_url = f"redis://:{quote(settings.REDIS_PASSWORD)}@{settings.REDIS_HOST}:{settings.REDIS_PORT}/{settings.REDIS_DB_CELERY_BROKER}" +_backend_url = f"redis://:{quote(settings.REDIS_PASSWORD)}@{settings.REDIS_HOST}:{settings.REDIS_PORT}/{settings.REDIS_DB_CELERY_BACKEND}" +os.environ["CELERY_BROKER_URL"] = _broker_url +os.environ["CELERY_RESULT_BACKEND"] = _backend_url +# Neutralize legacy Celery env vars that can be hijacked by Celery's CLI/Click +# integration and accidentally override our canonical URLs. +os.environ.pop("BROKER_URL", None) +os.environ.pop("RESULT_BACKEND", None) +os.environ.pop("CELERY_BROKER", None) +os.environ.pop("CELERY_BACKEND", None) + celery_app = Celery( "redbear_tasks", - broker=f"redis://:{quote(settings.REDIS_PASSWORD)}@{settings.REDIS_HOST}:{settings.REDIS_PORT}/{settings.CELERY_BROKER}", - backend=f"redis://:{quote(settings.REDIS_PASSWORD)}@{settings.REDIS_HOST}:{settings.REDIS_PORT}/{settings.CELERY_BACKEND}", + broker=_broker_url, + backend=_backend_url, ) +logger.info( + "Celery app initialized", + extra={ + "broker": _broker_url.replace(quote(settings.REDIS_PASSWORD), "***"), + "backend": _backend_url.replace(quote(settings.REDIS_PASSWORD), "***"), + }, +) # Default queue for unrouted tasks celery_app.conf.task_default_queue = 'memory_tasks' diff --git a/api/app/core/config.py b/api/app/core/config.py index 4afb1bc9..ba17da93 100644 --- a/api/app/core/config.py +++ b/api/app/core/config.py @@ -190,8 +190,10 @@ class Settings: LOG_FILE_MAX_SIZE_MB: int = int(os.getenv("LOG_FILE_MAX_SIZE_MB", "10")) # 10MB # Celery configuration (internal) - CELERY_BROKER: int = int(os.getenv("CELERY_BROKER", "1")) - CELERY_BACKEND: int = int(os.getenv("CELERY_BACKEND", "2")) + # NOTE: 变量名不以 CELERY_ 开头,避免被 Celery CLI 的前缀匹配机制劫持 + # 详见 docs/celery-env-bug-report.md + REDIS_DB_CELERY_BROKER: int = int(os.getenv("REDIS_DB_CELERY_BROKER", "1")) + REDIS_DB_CELERY_BACKEND: int = int(os.getenv("REDIS_DB_CELERY_BACKEND", "2")) # SMTP Email Configuration SMTP_SERVER: str = os.getenv("SMTP_SERVER", "smtp.gmail.com") diff --git a/api/env.example b/api/env.example index 1dc4536c..bd7f3dae 100644 --- a/api/env.example +++ b/api/env.example @@ -29,10 +29,10 @@ REDIS_DB= REDIS_PASSWORD=password #celery -BROKER_URL= -RESULT_BACKEND= -CELERY_BROKER= -CELERY_BACKEND= +# NOTE: 不要使用 BROKER_URL / RESULT_BACKEND / CELERY_BROKER / CELERY_BACKEND, +# 这些名称会被 Celery CLI 劫持,详见 docs/celery-env-bug-report.md +REDIS_DB_CELERY_BROKER= +REDIS_DB_CELERY_BACKEND= # Memory Cache Regeneration Configuration # Interval in hours for regenerating memory insight and user summary cache