import json import time from typing import Any from loguru import logger from surugaya_common.parsers.surugaya import SurugayaOrderDetailParser from src.tasks.base import BasePurchaseTask from task_queue.redis_manager import get_redis_client class SurugayaTradeMonitorTask(BasePurchaseTask): """ 骏河屋交易订单获取任务。 入参约定: - topic: surugaya_trade_monitor - payload.trade_list: 交易单号列表 """ async def execute(self) -> dict[str, Any]: self.report_event = "surugaya_trade_monitor" self.is_report = False redis_client = None trade_code = "" try: logger.debug(f"[任务 {self.task_id}] 骏河屋交易订单获取工作流已启动。") if not self.page: raise ValueError("页面对象未初始化,无法执行交易订单获取任务。") payload = self.message.get("payload", {}) trade_code = payload.get("trade_code", "") if not trade_code: err_msg = f"无法解析交易单号 '{trade_code}'。" logger.error(err_msg) raise ValueError(err_msg) page = self.page await page.goto(f"https://www.suruga-ya.jp/pcmypage/action_sell_search/detail?trade_code={trade_code}", wait_until="domcontentloaded", timeout=30000) order_detail_model = await SurugayaOrderDetailParser.parse_page(page) order_detail = order_detail_model.model_dump(mode="json") if order_detail_model else None logger.info(f"[任务 {self.task_id}] 骏河屋交易订单获取工作流执行成功,订单详情:{order_detail}") # 写入hash表 if not order_detail: raise Exception(f"交易单号 '{trade_code}' 未解析到订单详情。") new_trade_status = order_detail_model.status.trade_status or "" trade_number = order_detail_model.summary.trade_number or None redis_client = get_redis_client() # 更新hash表 hash_key = self.get_hash_key() delay_zset_key = self.get_delay_zset_key() requeue_member = json.dumps({"trade_code": trade_code}, ensure_ascii=False) # 获取上次保存的订单状态 old_trade_status = None existing_order_detail = await redis_client.hget(hash_key, trade_code) if existing_order_detail: old_trade_status = json.loads(existing_order_detail)["status"]["trade_status"] if old_trade_status and old_trade_status != new_trade_status: logger.info(f"[任务 {self.task_id}] 订单状态发生改变,需要上报。") self.is_report = True await redis_client.hset( hash_key, trade_code, json.dumps(order_detail, ensure_ascii=False), ) logger.info( f"[任务 {self.task_id}] 已将订单详情写入 Redis Hash '{hash_key}',field='{trade_code}'。" ) enqueue = True # 是否需要再次入队 if trade_number is not None: logger.warning( f"[任务 {self.task_id}] 订单物流单号已获取到 '{trade_number}',放弃再次入队。" ) enqueue = False elif new_trade_status == "発送済み" or new_trade_status == "取引終了": logger.warning(f"[任务 {self.task_id}] 订单状态为 '{new_trade_status}',放弃再次入队。") enqueue = False # 任务再次入队 if enqueue: next_score = int(time.time()) + self.get_delay_interval_seconds() await redis_client.zadd(delay_zset_key, {requeue_member: next_score}) logger.info( f"[任务 {self.task_id}] 延时任务已重新入队,key='{delay_zset_key}',score={next_score}。" ) return { "trade_code": trade_code, "order_detail": order_detail, } except Exception as e: self.is_report = False logger.error(f"[任务 {self.task_id}] 骏河屋交易订单获取工作流执行失败,错误信息:{e}") raise e