fix: 修复 PDD 页面误判与失败回执 (#35)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,"
|
||||
|
||||
Reference in New Issue
Block a user