celery任务改为异步访问数据库
This commit is contained in:
@@ -3,11 +3,10 @@
|
||||
包含与回调处理相关的业务逻辑函数
|
||||
"""
|
||||
import json
|
||||
import time
|
||||
import asyncio
|
||||
import httpx
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple, Dict, Any
|
||||
from sqlalchemy import text
|
||||
from fastapi import Request
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.config import settings
|
||||
@@ -95,8 +94,8 @@ async def log_callback_request(
|
||||
return False
|
||||
|
||||
|
||||
def save_callback_data_items(
|
||||
conn,
|
||||
async def save_callback_data_items(
|
||||
db: AsyncSession,
|
||||
callback_data_items: list,
|
||||
callback_failure_log_id: int
|
||||
) -> bool:
|
||||
@@ -105,12 +104,14 @@ def save_callback_data_items(
|
||||
Returns:
|
||||
bool: 保存是否成功,True表示成功,False表示失败或跳过保存
|
||||
"""
|
||||
from sqlalchemy import text
|
||||
|
||||
try:
|
||||
|
||||
logger.info(f"📊 共传入callback_log_id {callback_failure_log_id} 的 {len(callback_data_items)} 条数据")
|
||||
|
||||
# 检查是否已经存在该callback_log_id的数据
|
||||
existing_data_result = conn.execute(
|
||||
existing_data_result = await db.execute(
|
||||
text("SELECT * FROM callback_failure_data WHERE callback_failure_log_id = :log_id"),
|
||||
{"log_id": callback_failure_log_id}
|
||||
)
|
||||
@@ -157,7 +158,7 @@ def save_callback_data_items(
|
||||
raw_data_json = json.dumps(item, ensure_ascii=False)
|
||||
|
||||
# 直接插入数据库
|
||||
conn.execute(
|
||||
await db.execute(
|
||||
text("""
|
||||
INSERT INTO callback_failure_data
|
||||
(callback_failure_log_id, phone_number, task_id, user_id, status, status_description, raw_data, calldate)
|
||||
@@ -175,17 +176,18 @@ def save_callback_data_items(
|
||||
}
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
await db.commit()
|
||||
logger.info(f"✅ 成功保存 {len(callback_data_items)} 条callback_data记录到数据库")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 保存callback_data到数据库失败: {e}", exc_info=True)
|
||||
await db.rollback()
|
||||
# 不重新抛出异常,避免影响主业务流程
|
||||
return False
|
||||
|
||||
|
||||
def get_uncompleted_callback_log(conn) -> Tuple[bool, Optional[Tuple[int, str, str, str]]]:
|
||||
async def get_uncompleted_callback_log(db: AsyncSession) -> Tuple[bool, Optional[Tuple[int, str, str, str]]]:
|
||||
"""获取一条未完成的回调请求(按创建时间取最小值)
|
||||
|
||||
Returns:
|
||||
@@ -193,9 +195,11 @@ def get_uncompleted_callback_log(conn) -> Tuple[bool, Optional[Tuple[int, str, s
|
||||
- 第一个值表示查询是否成功(True表示成功,False表示失败)
|
||||
- 第二个值为回调日志数据元组或None
|
||||
"""
|
||||
from sqlalchemy import text
|
||||
|
||||
try:
|
||||
# 查询一条未完成的回调日志(按创建时间升序排列,取第一条)
|
||||
result = conn.execute(
|
||||
result = await db.execute(
|
||||
text("""
|
||||
SELECT id, site_id, request_headers, request_body
|
||||
FROM callback_failure_logs
|
||||
@@ -221,11 +225,13 @@ def get_uncompleted_callback_log(conn) -> Tuple[bool, Optional[Tuple[int, str, s
|
||||
return False, None
|
||||
|
||||
|
||||
def get_callback_log_data(conn, callback_log_id: int) -> Tuple[bool, Optional[str], Optional[str]]:
|
||||
async def get_callback_log_data(db: AsyncSession, callback_log_id: int) -> Tuple[bool, Optional[str], Optional[str]]:
|
||||
"""获取回调日志数据"""
|
||||
from sqlalchemy import text
|
||||
|
||||
try:
|
||||
# 查询回调日志
|
||||
result = conn.execute(
|
||||
result = await db.execute(
|
||||
text("SELECT request_headers, request_body FROM callback_failure_logs WHERE id = :log_id"),
|
||||
{"log_id": callback_log_id}
|
||||
)
|
||||
@@ -245,8 +251,8 @@ def get_callback_log_data(conn, callback_log_id: int) -> Tuple[bool, Optional[st
|
||||
return False, None, None
|
||||
|
||||
|
||||
def call_external_api_with_retry(
|
||||
conn,
|
||||
async def call_external_api_with_retry(
|
||||
db: AsyncSession,
|
||||
request_body: dict,
|
||||
request_headers: Dict[str, str],
|
||||
max_retries: int,
|
||||
@@ -257,16 +263,16 @@ def call_external_api_with_retry(
|
||||
try:
|
||||
logger.info(f"🌐 尝试调用外部API接口,第{attempt}次")
|
||||
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.post(
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(
|
||||
settings.external_api_url,
|
||||
json=request_body,
|
||||
headers=request_headers
|
||||
)
|
||||
|
||||
# 记录推送日志
|
||||
_log_dtc_push_call(
|
||||
conn=conn,
|
||||
await _log_dtc_push_call(
|
||||
db=db,
|
||||
callback_failure_log_id=callback_failure_log_id,
|
||||
request_url=settings.external_api_url,
|
||||
request_headers=request_headers,
|
||||
@@ -297,18 +303,20 @@ def call_external_api_with_retry(
|
||||
|
||||
# 如果不是最后一次尝试,等待一段时间再重试
|
||||
if attempt < max_retries:
|
||||
time.sleep(2 ** attempt) # 指数退避
|
||||
await asyncio.sleep(2 ** attempt) # 指数退避
|
||||
|
||||
# 所有重试都失败了
|
||||
logger.error(f"❌ 调用外部API接口失败,已重试{max_retries}次")
|
||||
return False, max_retries
|
||||
|
||||
|
||||
def mark_callback_log_completed(conn, callback_log_id: int) -> bool:
|
||||
async def mark_callback_log_completed(db: AsyncSession, callback_log_id: int) -> bool:
|
||||
"""标记CallbackFailureLog记录为已完成"""
|
||||
from sqlalchemy import text
|
||||
|
||||
try:
|
||||
# 先检查推送日志中是否有响应成功的记录
|
||||
success_result = conn.execute(
|
||||
success_result = await db.execute(
|
||||
text("""
|
||||
SELECT COUNT(*) as success_count
|
||||
FROM external_api_logs
|
||||
@@ -326,7 +334,7 @@ def mark_callback_log_completed(conn, callback_log_id: int) -> bool:
|
||||
logger.info(f"✅ 回调日志 {callback_log_id} 找到 {success_count} 条成功推送记录,开始标记为完成")
|
||||
|
||||
# 更新指定日志记录为已完成
|
||||
result = conn.execute(
|
||||
result = await db.execute(
|
||||
text("""
|
||||
UPDATE callback_failure_logs
|
||||
SET is_completed = true
|
||||
@@ -341,18 +349,18 @@ def mark_callback_log_completed(conn, callback_log_id: int) -> bool:
|
||||
logger.warning(f"⚠️ 回调日志 {callback_log_id} 已标记为完成或不存在")
|
||||
return False
|
||||
|
||||
conn.commit()
|
||||
await db.commit()
|
||||
logger.info(f"✅ 回调日志 {callback_log_id} 已标记为完成")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 标记回调日志 {callback_log_id} 完成失败: {e}", exc_info=True)
|
||||
conn.rollback()
|
||||
await db.rollback()
|
||||
return False
|
||||
|
||||
|
||||
def get_related_records_by_unique_data_list(
|
||||
conn,
|
||||
async def get_related_records_by_unique_data_list(
|
||||
db: AsyncSession,
|
||||
unique_data_list: list,
|
||||
callback_log_id: int,
|
||||
limit_count: int
|
||||
@@ -360,7 +368,7 @@ def get_related_records_by_unique_data_list(
|
||||
"""根据unique_data_list中的数据查询相关记录,按创建时间排序
|
||||
|
||||
Args:
|
||||
conn: 数据库连接
|
||||
db: 异步数据库会话
|
||||
unique_data_list: 包含手机号、task_id、user_id的数据项列表
|
||||
callback_log_id: 回调日志ID,作为过滤条件
|
||||
limit_count: 获取记录数量限制
|
||||
@@ -370,6 +378,8 @@ def get_related_records_by_unique_data_list(
|
||||
- 第一个值表示查询是否成功(True表示成功,False表示失败)
|
||||
- 第二个值为查询到的相关记录列表,失败时返回空列表
|
||||
"""
|
||||
from sqlalchemy import text
|
||||
|
||||
related_records = []
|
||||
|
||||
try:
|
||||
@@ -387,7 +397,7 @@ def get_related_records_by_unique_data_list(
|
||||
user_id = item.get('user_id', '')
|
||||
|
||||
if phone_number and task_id and user_id:
|
||||
result = conn.execute(
|
||||
result = await db.execute(
|
||||
text("""
|
||||
SELECT phone_number, task_id, user_id, created_at
|
||||
FROM callback_failure_data
|
||||
@@ -427,8 +437,8 @@ def get_related_records_by_unique_data_list(
|
||||
return False, []
|
||||
|
||||
|
||||
def _log_dtc_push_call(
|
||||
conn,
|
||||
async def _log_dtc_push_call(
|
||||
db: AsyncSession,
|
||||
callback_failure_log_id: int,
|
||||
request_url: str,
|
||||
request_headers: Dict[str, Any],
|
||||
@@ -439,6 +449,8 @@ def _log_dtc_push_call(
|
||||
retry_count: int
|
||||
) -> bool:
|
||||
"""记录DTC推送调用日志"""
|
||||
from sqlalchemy import text
|
||||
|
||||
try:
|
||||
# 提取手机号从请求体中
|
||||
phone_number = None
|
||||
@@ -448,7 +460,7 @@ def _log_dtc_push_call(
|
||||
phone_number = first_item['number_data']['number']
|
||||
|
||||
# 记录到external_api_logs表
|
||||
conn.execute(
|
||||
await db.execute(
|
||||
text("""
|
||||
INSERT INTO external_api_logs (
|
||||
callback_failure_log_id,
|
||||
@@ -487,11 +499,11 @@ def _log_dtc_push_call(
|
||||
}
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
await db.commit()
|
||||
logger.debug(f"📝 DTC推送调用日志记录成功,状态码: {response_status}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 记录DTC推送调用日志失败: {e}", exc_info=True)
|
||||
conn.rollback()
|
||||
await db.rollback()
|
||||
return False
|
||||
Reference in New Issue
Block a user