最新版生产环境后端
This commit is contained in:
114
utils/celery_utils.py
Normal file
114
utils/celery_utils.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""
|
||||
阿龙电竞 - Celery工具函数
|
||||
提供通用的Celery辅助函数,确保数据安全和操作稳定
|
||||
【修复版】已解决装饰器导致Celery任务无法识别的问题
|
||||
"""
|
||||
|
||||
import logging
|
||||
from django.db import transaction
|
||||
from datetime import datetime
|
||||
from decimal import Decimal, InvalidOperation
|
||||
import functools # 【核心修复】必须导入此模块
|
||||
|
||||
# 配置日志
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def safe_decimal_operation(value, default=Decimal('0.00')):
|
||||
"""
|
||||
安全处理Decimal操作,防止类型转换错误
|
||||
:param value: 输入值
|
||||
:param default: 默认值
|
||||
:return: Decimal对象
|
||||
"""
|
||||
try:
|
||||
if value is None:
|
||||
return default
|
||||
|
||||
if isinstance(value, Decimal):
|
||||
return value
|
||||
|
||||
if isinstance(value, (int, float)):
|
||||
return Decimal(str(value))
|
||||
|
||||
if isinstance(value, str):
|
||||
# 移除可能的空白字符和特殊字符
|
||||
value = value.strip()
|
||||
if not value:
|
||||
return default
|
||||
return Decimal(value)
|
||||
|
||||
# 其他类型尝试转换
|
||||
return Decimal(str(value))
|
||||
except (InvalidOperation, TypeError, ValueError) as e:
|
||||
logger.warning(f"Decimal转换失败: {e}, 输入值: {value}, 类型: {type(value)}, 使用默认值: {default}")
|
||||
return default
|
||||
except Exception as e:
|
||||
logger.error(f"Decimal转换发生未知错误: {e}, 输入值: {value}, 使用默认值: {default}")
|
||||
return default
|
||||
|
||||
def log_task_execution(task_name, success=True, details=""):
|
||||
"""
|
||||
记录任务执行日志
|
||||
:param task_name: 任务名称
|
||||
:param success: 是否成功
|
||||
:param details: 详细信息
|
||||
"""
|
||||
try:
|
||||
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
status = "成功" if success else "失败"
|
||||
|
||||
log_message = f"[{timestamp}] {task_name} - {status}"
|
||||
if details:
|
||||
log_message += f" | {details}"
|
||||
|
||||
if success:
|
||||
logger.info(log_message)
|
||||
else:
|
||||
logger.error(log_message)
|
||||
|
||||
return log_message
|
||||
except Exception as e:
|
||||
# 即使日志记录失败也不影响主流程
|
||||
print(f"日志记录失败: {e}")
|
||||
return f"日志记录失败: {e}"
|
||||
|
||||
def rollback_on_failure(operation_name):
|
||||
"""
|
||||
事务回滚装饰器(修复版)
|
||||
:param operation_name: 操作名称
|
||||
"""
|
||||
def decorator(func):
|
||||
@functools.wraps(func) # 【核心修复】保留原函数元数据,使Celery能正确识别任务
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
logger.error(f"{operation_name}事务执行失败: {str(e)}")
|
||||
raise
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
def retry_on_failure(max_retries=3, delay=60):
|
||||
"""
|
||||
重试装饰器(修复版,可用于Celery任务)
|
||||
:param max_retries: 最大重试次数
|
||||
:param delay: 重试延迟(秒)
|
||||
"""
|
||||
def decorator(func):
|
||||
@functools.wraps(func) # 【核心修复】保留原函数元数据
|
||||
def wrapper(*args, **kwargs):
|
||||
retries = 0
|
||||
while retries < max_retries:
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
retries += 1
|
||||
if retries == max_retries:
|
||||
logger.error(f"任务{func.__name__}重试{max_retries}次后失败: {str(e)}")
|
||||
raise
|
||||
logger.warning(f"任务{func.__name__}第{retries}次失败,{delay}秒后重试: {str(e)}")
|
||||
import time
|
||||
time.sleep(delay)
|
||||
return wrapper
|
||||
return decorator
|
||||
Reference in New Issue
Block a user