feat: 任务失败后继续执行下一条 (#170)

This commit is contained in:
chengma
2026-08-11 18:21:25 +08:00
parent b2c99840b3
commit 8b8a542cc5
14 changed files with 280 additions and 103 deletions
+12 -12
View File
@@ -241,11 +241,11 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_one_local()
self.assertEqual(outcome.kind, "failed")
self.assertEqual(outcome.kind, "task_failed")
self.assertNotIn(("enter_confirmation",), adapter.calls)
detail = self.repository.get_task("PUR-001")
assert detail is not None
self.assertEqual(detail.status, TaskStatus.MANUAL_REVIEW)
self.assertEqual(detail.status, TaskStatus.FAILED)
self.assertEqual(detail.last_error_code, "PURCHASE_PRICE_EXCEEDED")
def test_unavailable_goods_stops_before_specs_and_is_not_retryable(self):
@@ -254,7 +254,7 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_one_local()
self.assertEqual("business_failed", outcome.kind)
self.assertEqual("task_failed", outcome.kind)
self.assertNotIn(("select_options", OPTIONS), adapter.calls)
detail = self.repository.get_task("PUR-001")
self.assertEqual(TaskStatus.FAILED, detail.status)
@@ -276,12 +276,12 @@ class PurchaseTaskServiceTest(unittest.TestCase):
def test_invalid_pages_and_ambiguous_target_fail_safely(self):
cases = (
("captcha", 1, "PDD_PAGE_CAPTCHA"),
("login_required", 1, "PDD_PAGE_LOGIN_REQUIRED"),
("unknown", 1, "PDD_PAGE_UNKNOWN"),
("", 2, "PURCHASE_AMBIGUOUS_TARGET"),
("captcha", 1, "PDD_PAGE_CAPTCHA", "global_failed"),
("login_required", 1, "PDD_PAGE_LOGIN_REQUIRED", "global_failed"),
("unknown", 1, "PDD_PAGE_UNKNOWN", "global_failed"),
("", 2, "PURCHASE_AMBIGUOUS_TARGET", "task_failed"),
)
for index, (page, candidates, expected_code) in enumerate(cases):
for index, (page, candidates, expected_code, expected_kind) in enumerate(cases):
with self.subTest(page=page, candidates=candidates):
task_id = f"PUR-BLOCK-{index}"
self._prepare_task(task_id=task_id)
@@ -292,7 +292,7 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_selected(task_id)
self.assertEqual(outcome.kind, "failed")
self.assertEqual(outcome.kind, expected_kind)
self.assertNotIn(("enter_confirmation",), adapter.calls)
detail = self.repository.get_task(task_id)
assert detail is not None
@@ -339,7 +339,7 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_one_local()
self.assertEqual(outcome.kind, "failed")
self.assertEqual(outcome.kind, "task_failed")
self.assertEqual(adapter.submit_count, 0)
run = self.repository.latest_task_run("PUR-001")
self.assertIsNone(run.irreversible_action_at)
@@ -364,7 +364,7 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_one_local()
self.assertEqual(outcome.kind, "failed")
self.assertEqual(outcome.kind, "task_failed")
self.assertEqual(adapter.calls, [("close",)])
run = self.repository.latest_task_run("PUR-001")
self.assertIsNone(run.irreversible_action_at)
@@ -400,7 +400,7 @@ class PurchaseTaskServiceTest(unittest.TestCase):
outcome = self._service(adapter).execute_selected(task_id)
self.assertEqual(outcome.kind, "failed")
self.assertEqual(outcome.kind, "task_failed")
self.assertNotIn(("open_goods", "https://example.test/goods"), adapter.calls)
detail = self.repository.get_task(task_id)
assert detail is not None