fix: Сохранять файл фото ДО запуска Celery task
При асинхронной обработке фото нужно сначала сохранить файл в БД,
потом запустить Celery task. Иначе task не найдет файл.
Изменения:
- BasePhoto.save() теперь сохраняет файл перед запуском task
- Исправлена проблема 'Photo has no image file' в Celery worker
🤖 Generated with Claude Code
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
=8F80;870F8O Celery 4;O 02B><0B8G5A:>9 703@C7:8 ?@8 AB0@B5 Django.
|
||||
|
||||
-B> 30@0=B8@C5B GB> Celery app 1C45B 8=8F80;878@>20= 2 <><5=B 70?CA:0 Django,
|
||||
GB> ?>72>;O5B @shared_task 45:>@0B>@C @01>B0BL ?@028;L=>.
|
||||
"""
|
||||
from .celery import app as celery_app
|
||||
|
||||
__all__ = ('celery_app',)
|
||||
|
||||
34
myproject/myproject/celery.py
Normal file
34
myproject/myproject/celery.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
Celery configuration for myproject with django-tenants support.
|
||||
|
||||
IMPORTANT: В мультитенантной среде все задачи должны:
|
||||
1. Получать schema_name в параметрах
|
||||
2. Активировать нужную схему через connection.set_schema()
|
||||
3. Это гарантирует изоляцию данных по тенантам
|
||||
"""
|
||||
import os
|
||||
import logging
|
||||
from celery import Celery
|
||||
from django.conf import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Указываем Django settings module
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
|
||||
|
||||
# Создаем Celery app
|
||||
app = Celery('myproject')
|
||||
|
||||
# Загружаем конфигурацию из Django settings с префиксом CELERY_
|
||||
app.config_from_object('django.conf:settings', namespace='CELERY')
|
||||
|
||||
# Автоматическое обнаружение tasks.py в приложениях
|
||||
# Это позволяет использовать @shared_task в любом приложении
|
||||
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||
|
||||
|
||||
@app.task(bind=True, ignore_result=True)
|
||||
def debug_task(self):
|
||||
"""Тестовая задача для проверки работы Celery"""
|
||||
print(f'Request: {self.request!r}')
|
||||
logger.info('Celery is working!')
|
||||
@@ -56,6 +56,9 @@ SHARED_APPS = [
|
||||
|
||||
# Accounts должен быть в shared для CustomUser (используется в админке)
|
||||
'accounts',
|
||||
|
||||
# Celery results (для сохранения статуса асинхронных задач)
|
||||
'django_celery_results',
|
||||
]
|
||||
|
||||
# Tenant apps: создаются в отдельной схеме для каждого тенанта (изолированные данные)
|
||||
@@ -357,3 +360,42 @@ TENANT_ADMIN_NAME = env('TENANT_ADMIN_NAME')
|
||||
# ============================================
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
|
||||
# ============================================
|
||||
# CELERY CONFIGURATION
|
||||
# ============================================
|
||||
|
||||
# Redis broker и backend для хранения результатов
|
||||
CELERY_BROKER_URL = f'redis://{env("REDIS_HOST", default="localhost")}:{env("REDIS_PORT", default="6379")}/{env("REDIS_DB", default="0")}'
|
||||
CELERY_RESULT_BACKEND = 'django-db' # Сохраняем результаты в БД (совместимо с мультитенантностью)
|
||||
|
||||
# Сериализация
|
||||
CELERY_ACCEPT_CONTENT = ['json']
|
||||
CELERY_TASK_SERIALIZER = 'json'
|
||||
CELERY_RESULT_SERIALIZER = 'json'
|
||||
CELERY_TIMEZONE = TIME_ZONE
|
||||
|
||||
# Task routing для разделения нагрузки
|
||||
CELERY_TASK_ROUTES = {
|
||||
'products.tasks.process_product_photo_async': {'queue': 'photo_processing'},
|
||||
'products.tasks.process_multiple_photos_async': {'queue': 'photo_processing'},
|
||||
}
|
||||
|
||||
# Worker настройки для обработки длительных задач
|
||||
CELERY_WORKER_PREFETCH_MULTIPLIER = 1 # Worker берет по одной задаче за раз
|
||||
CELERY_TASK_ACKS_LATE = True # Подтверждаем задачу только после успешного выполнения
|
||||
CELERY_WORKER_MAX_TASKS_PER_CHILD = 50 # Перезапускаем worker после 50 задач (защита от утечек памяти PIL)
|
||||
|
||||
# Timeouts
|
||||
CELERY_TASK_TIME_LIMIT = 300 # 5 минут максимум на одну задачу
|
||||
CELERY_TASK_SOFT_TIME_LIMIT = 240 # 4 минуты - мягкий лимит перед жестким
|
||||
|
||||
# Результаты и события
|
||||
CELERY_RESULT_EXPIRES = 3600 # Результаты хранятся 1 час (достаточно для отслеживания прогресса)
|
||||
CELERY_WORKER_SEND_TASK_EVENTS = True # Отправляем события для мониторинга
|
||||
CELERY_TASK_SEND_SENT_EVENT = True
|
||||
|
||||
# Retry настройки
|
||||
CELERY_TASK_DEFAULT_MAX_RETRIES = 3
|
||||
CELERY_TASK_DEFAULT_RETRY_DELAY = 60 # Повторить через 60 секунд при ошибке
|
||||
|
||||
Reference in New Issue
Block a user