from __future__ import annotations import queue from browser_pool_worker import BrowserWorker class _AlwaysFailEnsureWorker(BrowserWorker): def __init__(self, *, worker_id: int, task_queue: queue.Queue): super().__init__(worker_id=worker_id, task_queue=task_queue, pre_warm=False) self.ensure_calls = 0 def _ensure_browser(self) -> bool: # noqa: D401 - matching base naming self.ensure_calls += 1 if self.ensure_calls >= 2: self.running = False return False def _close_browser(self): self.browser_instance = None def test_requeue_task_when_browser_unavailable(): task_queue: queue.Queue = queue.Queue() callback_calls: list[tuple[object, object]] = [] def callback(result, error): callback_calls.append((result, error)) task = { "func": lambda *_args, **_kwargs: None, "args": (), "kwargs": {}, "callback": callback, "retry_count": 0, } worker = _AlwaysFailEnsureWorker(worker_id=1, task_queue=task_queue) worker.start() task_queue.put(task) worker.join(timeout=5) assert worker.is_alive() is False assert worker.ensure_calls == 2 # 本地最多尝试2次创建浏览器 assert callback_calls == [] # 第一次失败会重新入队,不应立即回调失败 requeued = task_queue.get_nowait() assert requeued["retry_count"] == 1 def test_fail_task_after_second_assignment(): task_queue: queue.Queue = queue.Queue() callback_calls: list[tuple[object, object]] = [] def callback(result, error): callback_calls.append((result, error)) task = { "func": lambda *_args, **_kwargs: None, "args": (), "kwargs": {}, "callback": callback, "retry_count": 1, # 已重新分配过1次 } worker = _AlwaysFailEnsureWorker(worker_id=1, task_queue=task_queue) worker.start() task_queue.put(task) worker.join(timeout=5) assert worker.is_alive() is False assert callback_calls == [(None, "浏览器不可用")] assert worker.total_tasks == 1 assert worker.failed_tasks == 1