feat: 增加采集任务重新执行入口 (#63)
This commit is contained in:
+150
-4
@@ -30,7 +30,7 @@ from PyQt5.QtCore import (
|
||||
pyqtSignal,
|
||||
pyqtSlot,
|
||||
)
|
||||
from qfluentwidgets import InfoBar, InfoBarPosition
|
||||
from qfluentwidgets import InfoBar, InfoBarPosition, MessageBox
|
||||
|
||||
from .admin_gateway import (
|
||||
AdminGatewayError,
|
||||
@@ -51,7 +51,7 @@ from .task_models import (
|
||||
TaskSummary,
|
||||
TaskType,
|
||||
)
|
||||
from .task_repository import TaskRepository
|
||||
from .task_repository import CollectRerunError, TaskRepository
|
||||
from .task_detail_view import TaskDetailWindow
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ class ClaimTaskWorker(QObject):
|
||||
client_service: CurrentClientService,
|
||||
android_device_service: SelectedAndroidDeviceService,
|
||||
collect_service_factory: Optional[CollectServiceFactory] = None,
|
||||
selected_task_id: str = "",
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._gateway = gateway
|
||||
@@ -149,6 +150,7 @@ class ClaimTaskWorker(QObject):
|
||||
self._android_device_service = android_device_service
|
||||
self._cancelled = False
|
||||
self._collect_service_factory = collect_service_factory
|
||||
self._selected_task_id = selected_task_id
|
||||
|
||||
def cancel(self) -> None:
|
||||
"""阻止尚未开始的领取;已领取的任务仍必须保存到本地。"""
|
||||
@@ -166,7 +168,7 @@ class ClaimTaskWorker(QObject):
|
||||
return
|
||||
android_serial = self._android_device_service.load()
|
||||
|
||||
result = CollectTaskService(
|
||||
service = CollectTaskService(
|
||||
self._gateway,
|
||||
self._task_repository,
|
||||
ClientInfo(
|
||||
@@ -176,7 +178,12 @@ class ClaimTaskWorker(QObject):
|
||||
android_serial or "",
|
||||
cancelled=lambda: self._cancelled,
|
||||
collect_service_factory=self._collect_service_factory,
|
||||
).execute_one()
|
||||
)
|
||||
result = (
|
||||
service.execute_selected(self._selected_task_id)
|
||||
if self._selected_task_id
|
||||
else service.execute_one()
|
||||
)
|
||||
if not self._cancelled or result.kind == "cancelled":
|
||||
self.outcome.emit(result.kind, result.message, result.task_id)
|
||||
except AdminGatewayError as exc:
|
||||
@@ -265,6 +272,7 @@ class PDDTaskPageEvent(QObject):
|
||||
|
||||
page.searchRequested.connect(self.search_tasks)
|
||||
page.refreshRequested.connect(self.refresh_tasks)
|
||||
page.rerunRequested.connect(self.request_rerun)
|
||||
page.autoFetchRequested.connect(self._request_claim_task)
|
||||
page.detailRequested.connect(self.show_task_detail)
|
||||
page.taskModel.loadMoreRequested.connect(self._load_page)
|
||||
@@ -294,6 +302,144 @@ class PDDTaskPageEvent(QObject):
|
||||
|
||||
self._reload()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def request_rerun(self, task_id: str) -> None:
|
||||
"""确认后在后台重新采集当前选中的一条终态任务。"""
|
||||
|
||||
if self._closing or not task_id:
|
||||
return
|
||||
if self._auto_fetch_running or self._claim_busy:
|
||||
self._show_rerun_warning(
|
||||
"暂时不能重新执行",
|
||||
"自动获取或其他采集正在运行,请停止并等待当前任务结束。",
|
||||
)
|
||||
return
|
||||
if self._claim_gateway_error or self._claim_gateway is None:
|
||||
self._show_rerun_warning(
|
||||
"重新执行不可用",
|
||||
self._claim_gateway_error or "Admin 提交服务未初始化",
|
||||
)
|
||||
return
|
||||
try:
|
||||
client_settings = self._client_service.load()
|
||||
android_serial = self._selected_android_device_service.load()
|
||||
except Exception:
|
||||
self._show_rerun_warning(
|
||||
"重新执行不可用", "无法读取本地设备设置,请到设置页检查。"
|
||||
)
|
||||
return
|
||||
if not client_settings.client_id:
|
||||
self._show_rerun_warning(
|
||||
"重新执行不可用", "请先在设置页保存当前设备号和设备名。"
|
||||
)
|
||||
return
|
||||
if not android_serial:
|
||||
self._show_rerun_warning(
|
||||
"重新执行不可用", "请先在设置页选择并保存 Android 设备。"
|
||||
)
|
||||
return
|
||||
try:
|
||||
detail = self._repository.validate_collect_rerun(task_id)
|
||||
except (CollectRerunError, ValueError) as exc:
|
||||
self._show_rerun_warning("不能重新执行", str(exc))
|
||||
return
|
||||
except Exception:
|
||||
self._show_rerun_warning(
|
||||
"不能重新执行", "无法读取任务状态,请检查数据库后重试。"
|
||||
)
|
||||
return
|
||||
|
||||
title = detail.title or "尚未获取标题"
|
||||
dialog = MessageBox(
|
||||
"确认重新采集",
|
||||
f"任务:{detail.remote_task_id}\n商品:{title}\n\n"
|
||||
"新结果会覆盖 Client 和 Admin 的当前采集数据,旧结果仍保留在执行记录中。",
|
||||
self._page.window(),
|
||||
)
|
||||
dialog.yesButton.setText("重新采集")
|
||||
dialog.cancelButton.setText("取消")
|
||||
dialog.cancelButton.setFocus()
|
||||
if not dialog.exec():
|
||||
return
|
||||
|
||||
try:
|
||||
self._repository.prepare_collect_rerun(task_id)
|
||||
except (CollectRerunError, ValueError) as exc:
|
||||
self._show_rerun_warning("不能重新执行", str(exc))
|
||||
self._reload()
|
||||
return
|
||||
except Exception:
|
||||
self._show_rerun_warning(
|
||||
"重新执行失败", "无法更新本地任务状态,请检查数据库后重试。"
|
||||
)
|
||||
return
|
||||
self._start_rerun_worker(task_id)
|
||||
|
||||
def _start_rerun_worker(self, task_id: str) -> None:
|
||||
"""启动只处理指定任务的工作线程。"""
|
||||
|
||||
assert self._claim_gateway is not None
|
||||
self._claim_busy = True
|
||||
self._page.set_rerun_running(True)
|
||||
self._page.set_engine_status(f"正在重新采集任务 {task_id}…")
|
||||
self._reload()
|
||||
|
||||
thread = QThread(self)
|
||||
worker = ClaimTaskWorker(
|
||||
self._claim_gateway,
|
||||
self._repository,
|
||||
self._client_service,
|
||||
self._selected_android_device_service,
|
||||
self._collect_service_factory,
|
||||
selected_task_id=task_id,
|
||||
)
|
||||
worker.moveToThread(thread)
|
||||
thread.started.connect(worker.run)
|
||||
worker.retryableFailed.connect(self._on_rerun_failed)
|
||||
worker.failed.connect(self._on_rerun_failed)
|
||||
worker.outcome.connect(self._on_rerun_outcome)
|
||||
worker.completed.connect(thread.quit)
|
||||
worker.completed.connect(worker.deleteLater)
|
||||
thread.finished.connect(thread.deleteLater)
|
||||
thread.finished.connect(self._on_rerun_thread_finished)
|
||||
self._claim_thread = thread
|
||||
self._claim_worker = worker
|
||||
thread.start()
|
||||
|
||||
@pyqtSlot(str, str, str)
|
||||
def _on_rerun_outcome(self, kind: str, message: str, _task_id: str) -> None:
|
||||
if self._closing:
|
||||
return
|
||||
self._reload()
|
||||
self._page.set_engine_status(message)
|
||||
if kind != "succeeded":
|
||||
self._show_claim_error("重新采集需要处理", message)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def _on_rerun_failed(self, message: str) -> None:
|
||||
if self._closing:
|
||||
return
|
||||
self._page.set_engine_status(message)
|
||||
self._show_claim_error("重新采集失败", message)
|
||||
|
||||
@pyqtSlot()
|
||||
def _on_rerun_thread_finished(self) -> None:
|
||||
self._claim_worker = None
|
||||
self._claim_thread = None
|
||||
self._claim_busy = False
|
||||
if not self._closing:
|
||||
self._page.set_rerun_running(False)
|
||||
|
||||
def _show_rerun_warning(self, title: str, content: str) -> None:
|
||||
InfoBar.warning(
|
||||
title=title,
|
||||
content=content,
|
||||
isClosable=True,
|
||||
duration=5000,
|
||||
position=InfoBarPosition.TOP_RIGHT,
|
||||
parent=self._page,
|
||||
)
|
||||
|
||||
@pyqtSlot()
|
||||
def _request_claim_task(self) -> None:
|
||||
"""切换持续自动获取;每一轮仍只启动一个后台 Worker。"""
|
||||
|
||||
Reference in New Issue
Block a user