fix: 修复 PDD 页面误判与失败回执 (#35)

This commit is contained in:
chengma
2026-08-07 17:58:30 +08:00
parent 51c2292be1
commit c59b4b0d59
11 changed files with 267 additions and 11 deletions
+22 -3
View File
@@ -1,5 +1,6 @@
"""使用 Python 标准库调用 Admin 登记和任务领取接口。"""
"""使用 Python 标准库调用 Admin 登记、领取和提交接口。"""
import hashlib
import json
import socket
from http.client import RemoteDisconnected
@@ -306,6 +307,24 @@ class HttpAdminGateway(AdminGateway):
accepted = data.get("accepted")
result_id = data.get("result_id")
accepted_at = data.get("accepted_at")
legacy_failure = (
endpoint == "failure"
and accepted is True
and isinstance(accepted_at, str)
and bool(accepted_at.strip())
and isinstance(data.get("task_status"), str)
and bool(data["task_status"].strip())
and not (isinstance(result_id, str) and result_id.strip())
)
if legacy_failure:
digest = hashlib.sha256(
idempotency_key.encode("utf-8")
).hexdigest()[:16]
return SubmissionReceipt(
True,
f"legacy-failure-{digest}",
accepted_at,
)
if (
accepted is not True
or not isinstance(result_id, str)
@@ -315,8 +334,8 @@ class HttpAdminGateway(AdminGateway):
):
raise AdminGatewayError(
"ADMIN_INVALID_RESPONSE",
"Admin 提交响应字段不完整",
False,
"Admin 返回成功状态,但响应格式异常,数据可能已接收,将安全重试",
True,
request_id,
)
return SubmissionReceipt(True, result_id, accepted_at)
+15 -6
View File
@@ -764,21 +764,30 @@ class PddCollectService:
raise PddCollectError("DEVICE_APP_START_FAILED", f"无法打开 PDD 商品链接:{exc}") from exc
deadline = self._monotonic() + self._page_timeout
last_labels: list[str] = []
while self._monotonic() < deadline:
self._check_cancelled()
current = device.app_current()
if current.get("package") == PDD_PACKAGE_NAME:
xml_data = device.dump_hierarchy()
root = _parse_xml(xml_data)
last_labels = _all_labels(root)
xml_data = device.dump_hierarchy()
self._last_goods_xml = str(xml_data)
self._goods_screens_checked += 1
root = _parse_xml(xml_data)
last_labels = _all_labels(root)
pdd_node_count = sum(
1
for node in root.iter("node")
if node.get("package") == PDD_PACKAGE_NAME
)
# 部分 OPPO/ColorOS 设备会一直把无线调试设置页报告为焦点,
# 即使屏幕和无障碍树已经是 PDD。此时以树中真实包名为准。
is_pdd_hierarchy = pdd_node_count >= 3
is_pdd_focused = current.get("package") == PDD_PACKAGE_NAME
if is_pdd_focused or is_pdd_hierarchy:
_raise_special_page(last_labels)
combined = " ".join(last_labels)
loading = "加载中" in combined or "正在加载" in combined
if not loading and any(marker in combined for marker in _READY_MARKERS):
return
self._sleep(0.5)
_raise_special_page(last_labels)
raise PddCollectError("PDD_PAGE_TIMEOUT", "等待 PDD 商品详情页加载超时")
def _collect_goods_details(self, device: Any) -> GoodsSnapshot:
+9
View File
@@ -163,6 +163,15 @@ class TaskRepository:
" WHERE status = 'sending'",
(now,),
)
# #35 之前,Admin 的失败响应缺少 result_id。Admin 实际已经
# 接收,但旧 Client 把这类 2xx 响应误标为永久失败。恢复为
# pending 后使用原幂等键重试,不会重复写入业务结果。
connection.execute(
"UPDATE outbox_events SET status = 'pending', updated_at = ?"
" WHERE status = 'failed'"
" AND last_error = 'Admin 提交响应字段不完整'",
(now,),
)
connection.execute(
"UPDATE pdd_tasks SET status = 'retry_wait',"
" current_step = 'interrupted', retry_count = retry_count + 1,"