实现租约恢复核对:verify_on_site 接真实订单列表反查
新增 SiteInteractor.list_recent_orders(分页拉 order.my.rakuten.co.jp 订单列表, 按商品 URL 反查)+ GatewayClient.get_task,替换掉恒返回 UNKNOWN 的桩。 NOT_ORDERED 分支目前只有逻辑验证、没有真实多单数据支撑,刻意仍路由到 needs_human,不自动重新下单。全程只读查询,未触发任何真实付款操作。
This commit is contained in:
@@ -40,11 +40,18 @@ class FakeGateway:
|
||||
renews: int = 0
|
||||
fail_report_with: Exception | None = None
|
||||
|
||||
# verify_on_site 恢复核对会调 get_task 拿 created_at;测试默认给一个可解析
|
||||
# 的时间戳,具体核对分支由 monkeypatch 替换 verify.verify_on_site 控制
|
||||
task_created_at: str = "2026-01-01T00:00:00Z"
|
||||
|
||||
async def lease(
|
||||
self, worker_id: str, *, wait: int = 30, site: str | None = None
|
||||
) -> LeaseTask | None:
|
||||
return None # 主循环测试不通过 lease 喂数据,直接调 handle
|
||||
|
||||
async def get_task(self, task_id: str) -> dict[str, Any]:
|
||||
return {"task_id": task_id, "created_at": self.task_created_at}
|
||||
|
||||
async def renew(self, task_id: str, worker_id: str) -> dict[str, Any]:
|
||||
self.renews += 1
|
||||
return {"task_id": task_id, "lease_expires_at": "2099-01-01T00:00:00Z"}
|
||||
@@ -193,15 +200,17 @@ async def test_already_finished_task_is_reported_not_re_executed(
|
||||
async def test_recovery_task_with_unknown_verdict_reports_needs_human(
|
||||
runner: WorkerRunner, local_db: LocalDB, monkeypatch
|
||||
):
|
||||
"""lease_count > 1 + verify 桩返回 unknown → 转 needs_human,不执行"""
|
||||
"""lease_count > 1 + verify 返回 unknown(intent 缺 item_url)→ 转 needs_human,不执行"""
|
||||
|
||||
# verify 桩默认返回 unknown,不用 monkeypatch
|
||||
# verify.verify_on_site 已是真实实现(2026-08-13),但 _make_task 默认 intent 为空,
|
||||
# 缺 item_url 时函数第一步就短路返回 unknown,不用 monkeypatch 也能测这条分支
|
||||
await runner.handle(_make_task(task_id="t1", lease_count=2))
|
||||
|
||||
gateway: FakeGateway = runner._gateway_for_test # type: ignore[attr-defined]
|
||||
terminal = gateway.last_terminal_report()
|
||||
assert terminal["terminal_status"] == TaskStatus.NEEDS_HUMAN
|
||||
assert "无法定论" in terminal["detail"]
|
||||
assert "unknown" in terminal["detail"]
|
||||
assert "item_url" in terminal["detail"]
|
||||
|
||||
|
||||
async def test_recovery_task_with_already_ordered_verdict_reports_succeeded(
|
||||
@@ -209,7 +218,7 @@ async def test_recovery_task_with_already_ordered_verdict_reports_succeeded(
|
||||
):
|
||||
"""lease_count > 1 + verify 返回 already_ordered → 补报 succeeded,不重新下单"""
|
||||
|
||||
async def _already_ordered(task): # noqa: ANN001
|
||||
async def _already_ordered(task, **kwargs): # noqa: ANN001
|
||||
return verify.VerifyResult(
|
||||
verdict=verify.VerifyVerdict.ALREADY_ORDERED,
|
||||
site_order_id="ord-1",
|
||||
@@ -226,8 +235,34 @@ async def test_recovery_task_with_already_ordered_verdict_reports_succeeded(
|
||||
assert terminal["site_order_id"] == "ord-1"
|
||||
assert terminal["terminal_status"] == TaskStatus.SUCCEEDED
|
||||
|
||||
# 本地 DB 也应当被标记为已完成
|
||||
assert await local_db.has_finished("t1") is True
|
||||
|
||||
async def test_recovery_task_with_not_ordered_verdict_still_reports_needs_human(
|
||||
runner: WorkerRunner, local_db: LocalDB, monkeypatch
|
||||
):
|
||||
"""lease_count > 1 + verify 确认 not_ordered → 仍转 needs_human,不自动重新下单
|
||||
|
||||
刻意的保守选择(见 runner._handle_recovery 里的注释):NOT_ORDERED 分支目前
|
||||
只有逻辑正确性,没有被真实多单数据验证过,放开自动重新执行前必须显式决定。
|
||||
"""
|
||||
|
||||
async def _not_ordered(task, **kwargs): # noqa: ANN001
|
||||
return verify.VerifyResult(
|
||||
verdict=verify.VerifyVerdict.NOT_ORDERED,
|
||||
detail="已核对任务创建时间之后的全部订单,未找到匹配商品",
|
||||
)
|
||||
|
||||
monkeypatch.setattr(verify, "verify_on_site", _not_ordered)
|
||||
|
||||
await runner.handle(_make_task(task_id="t1", lease_count=2))
|
||||
|
||||
gateway: FakeGateway = runner._gateway_for_test # type: ignore[attr-defined]
|
||||
terminal = gateway.last_terminal_report()
|
||||
assert terminal["terminal_status"] == TaskStatus.NEEDS_HUMAN
|
||||
assert "not_ordered" in terminal["detail"]
|
||||
|
||||
# needs_human 分支不标记本地完成(与 UNKNOWN 分支一致):只有 ALREADY_ORDERED
|
||||
# 才 mark_finished,避免把「转人工」误当成本地已完成的终态
|
||||
assert await local_db.has_finished("t1") is False
|
||||
|
||||
|
||||
# ---- 站点交互未实现 → needs_human(§10 接口缝)----
|
||||
|
||||
Reference in New Issue
Block a user