Исправлена гонка БД при async обработке первого фото комплекта
- Добавлен retry на 5 сек при DoesNotExist для ожидания коммита транзакции - temp_path сохраняется в PhotoProcessingStatus.result_data при постановке задачи - При окончательной неудаче not_found удаляется осиротевший temp файл - Предотвращает накопление temp файлов при гонке создания фото
This commit is contained in:
@@ -101,9 +101,26 @@ def process_product_photo_async(self, photo_id, photo_model_class, schema_name):
|
||||
}
|
||||
}
|
||||
|
||||
except PhotoModel.DoesNotExist:
|
||||
except PhotoModel.DoesNotExist as e:
|
||||
logger.error(f"[Celery] Photo {photo_id} not found in schema {schema_name}")
|
||||
return {'status': 'error', 'reason': 'not_found', 'photo_id': photo_id}
|
||||
# Retry briefly to allow DB transaction to commit (race condition on first photo)
|
||||
try:
|
||||
raise self.retry(exc=e, countdown=5)
|
||||
except self.MaxRetriesExceededError:
|
||||
# Final failure: attempt to delete the orphan temp file if we recorded it
|
||||
try:
|
||||
from .models.photos import PhotoProcessingStatus
|
||||
status = (PhotoProcessingStatus.objects
|
||||
.filter(photo_id=photo_id, photo_model=photo_model_class)
|
||||
.order_by('-created_at')
|
||||
.first())
|
||||
temp_path = (status.result_data or {}).get('temp_path') if status else None
|
||||
if temp_path and default_storage.exists(temp_path):
|
||||
default_storage.delete(temp_path)
|
||||
logger.info(f"[Celery] Deleted temp file (not_found): {temp_path}")
|
||||
except Exception as del_exc:
|
||||
logger.warning(f"[Celery] Could not delete temp file for photo {photo_id} on not_found: {del_exc}")
|
||||
return {'status': 'error', 'reason': 'not_found', 'photo_id': photo_id}
|
||||
|
||||
except Exception as exc:
|
||||
logger.error(f"[Celery] Error processing photo {photo_id} in {schema_name}: {str(exc)}",
|
||||
|
||||
Reference in New Issue
Block a user