mirror of
https://git.oceanpay.cc/danial/kami_apple_exchage.git
synced 2025-12-18 22:29:09 +00:00
- 新增链接权重字段,支持1-100范围设置 - 修改轮询算法为基于权重的选择机制 - 更新链接API接口返回统一使用LinkInfo模型 - 添加更新链接权重的PATCH端点 - 调整链接仓库查询逻辑,只包含激活状态链接 - 迁移链接相关Pydantic模型到task模块统一管理 - 修改分页响应格式为通用PaginatedResponse包装 - 禁用OpenTelemetry监控配置
440 lines
16 KiB
Python
440 lines
16 KiB
Python
"""
|
||
任务服务层
|
||
处理任务相关的业务逻辑
|
||
"""
|
||
|
||
import traceback
|
||
from datetime import datetime
|
||
from typing import Any, Optional
|
||
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.core.log import get_logger
|
||
from app.core.state_manager import StateType, TaskState, task_state_manager
|
||
from app.enums.task import OrderTaskStatus
|
||
from app.repositories.task_repository import TaskRepository
|
||
from app.schemas.task import (
|
||
CardInfo,
|
||
GiftCardSubmissionRequest,
|
||
GiftCardSubmissionResponse,
|
||
GiftCardDetailCreate,
|
||
LinkInfo,
|
||
TaskListItem,
|
||
TaskListResponse,
|
||
UserInfo,
|
||
)
|
||
from app.services.gift_card_service import GiftCardService
|
||
|
||
logger = get_logger(__name__)
|
||
|
||
|
||
class TaskService:
|
||
"""任务服务类"""
|
||
|
||
def __init__(self, db: AsyncSession):
|
||
self.db = db
|
||
self.task_repo = TaskRepository(db)
|
||
|
||
async def get_task_list(self) -> TaskListResponse:
|
||
"""
|
||
获取任务列表
|
||
|
||
Returns:
|
||
TaskListResponse: 任务列表响应
|
||
"""
|
||
try:
|
||
# 获取所有任务状态
|
||
all_states = await task_state_manager.state_manager.list_states(
|
||
StateType.TASK
|
||
)
|
||
all_tasks = [state for state in all_states if isinstance(state, TaskState)]
|
||
|
||
task_list = []
|
||
|
||
for task in all_tasks:
|
||
|
||
# 创建任务列表项
|
||
task_item = TaskListItem(
|
||
# 任务状态相关字段
|
||
task_id=task.identifier,
|
||
worker_id=task.worker_id,
|
||
status=task.status,
|
||
progress=task.progress,
|
||
created_at=task.created_at.isoformat() if task.created_at else "",
|
||
updated_at=task.updated_at.isoformat() if task.updated_at else "",
|
||
completed_at=(
|
||
task.completed_at.isoformat() if task.completed_at else None
|
||
),
|
||
failed_at=task.failed_at.isoformat() if task.failed_at else None,
|
||
error_message=task.error_message,
|
||
# 订单数据库字段(默认为空,将在 enrich 方法中填充)
|
||
order_id=task.worker_id,
|
||
order_status=None,
|
||
final_order_url=None,
|
||
order_failure_reason=None,
|
||
order_completed_at=None,
|
||
order_created_at=None,
|
||
order_updated_at=None,
|
||
order_is_deleted=None,
|
||
order_deleted_at=None,
|
||
# 关联数据(将在 enrich 方法中填充)
|
||
user_info=None,
|
||
link_info=None,
|
||
card_info=None,
|
||
)
|
||
|
||
# 如果有订单ID,获取关联的用户、链接和礼品卡信息
|
||
order_id = task_item.order_id
|
||
if order_id:
|
||
task_item = await self._enrich_task_with_order_data(
|
||
task_item, order_id
|
||
)
|
||
|
||
task_list.append(task_item)
|
||
|
||
return TaskListResponse(
|
||
success=True,
|
||
tasks=task_list,
|
||
total=len(task_list),
|
||
message="获取任务列表成功",
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取任务列表失败: {traceback.format_exc()}")
|
||
raise
|
||
|
||
async def _enrich_task_with_order_data(
|
||
self, task_item: TaskListItem, order_id: str
|
||
) -> TaskListItem:
|
||
"""
|
||
使用订单数据丰富任务信息,包含完整的数据库字段
|
||
|
||
Args:
|
||
task_item: 任务项
|
||
order_id: 订单ID
|
||
|
||
Returns:
|
||
TaskListItem: 丰富后的任务项,包含所有数据库字段
|
||
"""
|
||
try:
|
||
# 查询订单及其所有关联数据
|
||
order = await self.task_repo.get_order_with_all_relations(order_id)
|
||
if not order:
|
||
return task_item
|
||
|
||
# 格式化时间函数
|
||
def format_datetime(dt: Any) -> str | None:
|
||
if dt:
|
||
return dt.isoformat() if hasattr(dt, "isoformat") else str(dt)
|
||
return None
|
||
|
||
# 准备用户信息
|
||
user_info = None
|
||
if order.user_data:
|
||
user_data = order.user_data
|
||
user_info = UserInfo(
|
||
id=user_data.id,
|
||
first_name=user_data.first_name,
|
||
last_name=user_data.last_name,
|
||
email=user_data.email,
|
||
phone=user_data.phone,
|
||
street_address=user_data.street_address,
|
||
city=user_data.city,
|
||
state=user_data.state,
|
||
zip_code=user_data.zip_code,
|
||
created_at=format_datetime(user_data.created_at),
|
||
updated_at=format_datetime(user_data.updated_at),
|
||
)
|
||
|
||
# 准备链接信息
|
||
link_info = None
|
||
if order.links:
|
||
link = order.links
|
||
link_info = LinkInfo(
|
||
weight=link.weight,
|
||
id=link.id,
|
||
url=link.url,
|
||
amount=link.amount,
|
||
status=link.status,
|
||
created_at=format_datetime(link.created_at),
|
||
updated_at=format_datetime(link.updated_at),
|
||
)
|
||
|
||
# 准备礼品卡信息(支持多张卡片)
|
||
card_info = None
|
||
gift_card_list = []
|
||
if isinstance(order.gift_cards, list):
|
||
gift_card_list = order.gift_cards
|
||
elif order.gift_cards:
|
||
gift_card_list.append(order.gift_cards)
|
||
|
||
if gift_card_list:
|
||
card_info = []
|
||
for gift_card in gift_card_list:
|
||
card_info_item = CardInfo(
|
||
id=gift_card.id,
|
||
card_code=gift_card.card_code,
|
||
card_value=gift_card.card_value,
|
||
status=gift_card.status.value,
|
||
failure_reason=gift_card.failure_reason,
|
||
order_id=gift_card.order_id,
|
||
created_at=format_datetime(gift_card.created_at),
|
||
updated_at=format_datetime(gift_card.updated_at),
|
||
)
|
||
card_info.append(card_info_item)
|
||
|
||
# 创建新的任务项,包含所有数据库字段
|
||
return TaskListItem(
|
||
# 任务状态相关字段
|
||
task_id=task_item.task_id,
|
||
worker_id=task_item.worker_id,
|
||
status=task_item.status,
|
||
progress=task_item.progress,
|
||
created_at=task_item.created_at,
|
||
updated_at=task_item.updated_at,
|
||
completed_at=task_item.completed_at,
|
||
failed_at=task_item.failed_at,
|
||
error_message=task_item.error_message,
|
||
# 订单数据库字段
|
||
order_id=order.id,
|
||
order_status=order.status.value,
|
||
final_order_url=order.final_order_url,
|
||
order_failure_reason=order.failure_reason,
|
||
order_completed_at=format_datetime(order.completed_at),
|
||
order_created_at=format_datetime(order.created_at),
|
||
order_updated_at=format_datetime(order.updated_at),
|
||
order_is_deleted=order.is_deleted,
|
||
order_deleted_at=format_datetime(order.deleted_at),
|
||
# 关联数据
|
||
user_info=user_info,
|
||
link_info=link_info,
|
||
card_info=card_info,
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取订单关联数据失败: {traceback.format_exc()}")
|
||
return task_item
|
||
|
||
async def submit_gift_card(
|
||
self, request: GiftCardSubmissionRequest
|
||
) -> GiftCardSubmissionResponse:
|
||
"""
|
||
提交礼品卡信息并更新任务状态
|
||
|
||
Args:
|
||
request: 礼品卡提交请求
|
||
|
||
Returns:
|
||
GiftCardSubmissionResponse: 操作结果
|
||
"""
|
||
try:
|
||
# 获取现有任务
|
||
task = await task_state_manager.get_task_state(request.task_id)
|
||
if not task:
|
||
raise ValueError("任务不存在")
|
||
|
||
# 更新任务结果,包含礼品卡信息
|
||
updated_result = task.result.copy() if task.result else {}
|
||
updated_result.update(
|
||
{
|
||
"card_code": request.card_code,
|
||
"card_value": request.card_value,
|
||
"submitted_at": datetime.now().isoformat(),
|
||
}
|
||
)
|
||
|
||
# 把礼品卡数据保存的数据库中
|
||
await GiftCardService(self.db).submit_gift_card_info(
|
||
GiftCardDetailCreate(
|
||
task_id=request.task_id,
|
||
card_code=request.card_code,
|
||
card_value=request.card_value,
|
||
)
|
||
)
|
||
|
||
logger.info(
|
||
f"礼品卡信息保存成功,任务ID: {request.task_id} 订单ID:{task.worker_id}"
|
||
)
|
||
# 更新任务状态为已接收礼品卡
|
||
success = await task_state_manager.set_task_state(
|
||
task_id=request.task_id,
|
||
worker_id=task.worker_id,
|
||
order_id=task.worker_id,
|
||
progress=72,
|
||
status=OrderTaskStatus.GIFT_CARD_RECEIVED,
|
||
result=updated_result,
|
||
)
|
||
|
||
if success:
|
||
logger.info(f"礼品卡提交成功,任务ID: {request.task_id}")
|
||
return GiftCardSubmissionResponse(
|
||
success=True, task_id=request.task_id, message="礼品卡提交成功"
|
||
)
|
||
else:
|
||
raise RuntimeError("更新任务状态失败")
|
||
|
||
except Exception as e:
|
||
logger.error(f"提交礼品卡失败: {e}")
|
||
raise
|
||
|
||
async def get_task_by_id(self, task_id: str) -> Optional[TaskListItem]:
|
||
"""
|
||
根据任务ID获取任务详情
|
||
|
||
Args:
|
||
task_id: 任务ID
|
||
|
||
Returns:
|
||
TaskListItem | None: 任务详情
|
||
"""
|
||
try:
|
||
task = await task_state_manager.get_task_state(task_id)
|
||
if not task:
|
||
return None
|
||
|
||
# 获取任务基础信息
|
||
task_dict = (
|
||
task.model_dump()
|
||
if hasattr(task, "model_dump")
|
||
else task.model_dump() if hasattr(task, "dict") else vars(task)
|
||
)
|
||
|
||
# 创建任务列表项
|
||
created_at = task_dict.get("created_at")
|
||
updated_at = task_dict.get("updated_at")
|
||
completed_at = task_dict.get("completed_at")
|
||
failed_at = task_dict.get("failed_at")
|
||
|
||
# 转换datetime为字符串
|
||
def format_datetime(dt: datetime | str | None) -> str | None:
|
||
if isinstance(dt, datetime):
|
||
return dt.isoformat()
|
||
elif isinstance(dt, str):
|
||
return dt
|
||
return None
|
||
|
||
task_item = TaskListItem(
|
||
# 任务状态相关字段
|
||
task_id=task_dict.get("identifier", ""),
|
||
worker_id=task_dict.get("worker_id"),
|
||
status=task_dict.get("status", ""),
|
||
progress=task_dict.get("progress", 0.0),
|
||
created_at=format_datetime(created_at) or "",
|
||
updated_at=format_datetime(updated_at) or "",
|
||
completed_at=format_datetime(completed_at),
|
||
failed_at=format_datetime(failed_at),
|
||
error_message=task_dict.get("error_message"),
|
||
# 订单数据库字段(默认为空,将在 enrich 方法中填充)
|
||
order_id=(
|
||
task_dict.get("result", {}).get("order_id")
|
||
if task_dict.get("result")
|
||
else None
|
||
),
|
||
order_status=None,
|
||
final_order_url=None,
|
||
order_failure_reason=None,
|
||
order_completed_at=None,
|
||
order_created_at=None,
|
||
order_updated_at=None,
|
||
order_is_deleted=None,
|
||
order_deleted_at=None,
|
||
# 关联数据(将在 enrich 方法中填充)
|
||
user_info=None,
|
||
link_info=None,
|
||
card_info=None,
|
||
)
|
||
|
||
# 如果有订单ID,获取关联的用户、链接和礼品卡信息
|
||
order_id = task.worker_id
|
||
if order_id:
|
||
task_item = await self._enrich_task_with_order_data(task_item, order_id)
|
||
|
||
return task_item
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取任务详情失败: {e}")
|
||
raise
|
||
|
||
async def get_tasks_by_status(self, status: str) -> list[TaskListItem]:
|
||
"""
|
||
根据状态获取任务列表
|
||
|
||
Args:
|
||
status: 任务状态
|
||
|
||
Returns:
|
||
list[TaskListItem]: 任务列表
|
||
"""
|
||
try:
|
||
all_tasks = await task_state_manager.state_manager.list_states(
|
||
StateType.TASK
|
||
)
|
||
|
||
filtered_tasks = []
|
||
for task in all_tasks:
|
||
task_dict = (
|
||
task.model_dump()
|
||
if hasattr(task, "model_dump")
|
||
else task.model_dump() if hasattr(task, "dict") else vars(task)
|
||
)
|
||
|
||
if task_dict.get("status") == status:
|
||
# 转换datetime为字符串
|
||
def format_datetime(dt: datetime | str | None) -> str | None:
|
||
if isinstance(dt, datetime):
|
||
return dt.isoformat()
|
||
elif isinstance(dt, str):
|
||
return dt
|
||
return None
|
||
|
||
created_at = task_dict.get("created_at")
|
||
updated_at = task_dict.get("updated_at")
|
||
completed_at = task_dict.get("completed_at")
|
||
failed_at = task_dict.get("failed_at")
|
||
|
||
task_item = TaskListItem(
|
||
# 任务状态相关字段
|
||
task_id=task_dict.get("identifier", ""),
|
||
worker_id=task_dict.get("worker_id"),
|
||
status=task_dict.get("status", ""),
|
||
progress=task_dict.get("progress", 0.0),
|
||
created_at=format_datetime(created_at) or "",
|
||
updated_at=format_datetime(updated_at) or "",
|
||
completed_at=format_datetime(completed_at),
|
||
failed_at=format_datetime(failed_at),
|
||
error_message=task_dict.get("error_message"),
|
||
# 订单数据库字段(默认为空,将在 enrich 方法中填充)
|
||
order_id=(
|
||
task_dict.get("result", {}).get("order_id")
|
||
if task_dict.get("result")
|
||
else None
|
||
),
|
||
order_status=None,
|
||
final_order_url=None,
|
||
order_failure_reason=None,
|
||
order_completed_at=None,
|
||
order_created_at=None,
|
||
order_updated_at=None,
|
||
order_is_deleted=None,
|
||
order_deleted_at=None,
|
||
# 关联数据(将在 enrich 方法中填充)
|
||
user_info=None,
|
||
link_info=None,
|
||
card_info=None,
|
||
)
|
||
|
||
# 如果有订单ID,获取关联的用户、链接和礼品卡信息
|
||
order_id = task_item.order_id
|
||
if order_id:
|
||
task_item = await self._enrich_task_with_order_data(
|
||
task_item, order_id
|
||
)
|
||
|
||
filtered_tasks.append(task_item)
|
||
|
||
return filtered_tasks
|
||
|
||
except Exception as e:
|
||
logger.error(f"根据状态获取任务失败: {e}")
|
||
raise
|