fix(product-suite): keep retries in current results
This commit is contained in:
+160
-37
@@ -697,6 +697,9 @@ class SuiteTaskState:
|
||||
settings: dict = field(default_factory=product_suite.default_suite_settings)
|
||||
current_job_ids: list = field(default_factory=list)
|
||||
show_history: bool = False
|
||||
generation_job_ids: list = field(default_factory=list)
|
||||
generation_mode: str = "batch"
|
||||
generation_retry_job_id: int = None
|
||||
worker: object = None
|
||||
thread: object = None
|
||||
generation_run_token: str = ""
|
||||
@@ -1582,6 +1585,9 @@ class ProductSuiteTab(QWidget):
|
||||
state.project_binding_state = ""
|
||||
state.last_saved_prompt = ""
|
||||
state.current_job_ids = []
|
||||
state.generation_job_ids = []
|
||||
state.generation_mode = "batch"
|
||||
state.generation_retry_job_id = None
|
||||
state.done = state.failed = state.total = 0
|
||||
state.started_at = None
|
||||
if state is self._displayed_state:
|
||||
@@ -2517,12 +2523,22 @@ class ProductSuiteTab(QWidget):
|
||||
if state is None:
|
||||
return
|
||||
if state.generation_running():
|
||||
retrying = state.generation_mode == "retry"
|
||||
if state.generation_stop_requested:
|
||||
self._status("正在停止当前套图任务", "warning")
|
||||
self._status(
|
||||
"正在停止当前图片重试"
|
||||
if retrying
|
||||
else "正在停止当前套图任务",
|
||||
"warning",
|
||||
)
|
||||
return
|
||||
if self._confirm(
|
||||
"停止生成套图",
|
||||
"确认取消当前任务吗?已提交任务会在安全边界停止。",
|
||||
"停止图片重试" if retrying else "停止生成套图",
|
||||
(
|
||||
"确认停止当前图片重试吗?已提交任务会在安全边界停止。"
|
||||
if retrying
|
||||
else "确认取消当前任务吗?已提交任务会在安全边界停止。"
|
||||
),
|
||||
destructive=True,
|
||||
):
|
||||
state.generation_stop_requested = True
|
||||
@@ -2533,14 +2549,21 @@ class ProductSuiteTab(QWidget):
|
||||
"stop_requested",
|
||||
)
|
||||
self._apply_running_state(state)
|
||||
self._status("已请求停止当前套图任务", "warning")
|
||||
self._status(
|
||||
"已请求停止当前图片重试"
|
||||
if retrying
|
||||
else "已请求停止当前套图任务",
|
||||
"warning",
|
||||
)
|
||||
return
|
||||
self.start_generation(state)
|
||||
|
||||
def start_generation(self, state, specs=None):
|
||||
def start_generation(self, state, specs=None, *, retry_job_id=None):
|
||||
if state.generation_running():
|
||||
self._status("当前套图任务仍在生成", "warning")
|
||||
return False
|
||||
retry_job_id = int(retry_job_id) if retry_job_id is not None else None
|
||||
retrying = retry_job_id is not None
|
||||
if state is self._displayed_state:
|
||||
self._save_controls_to_state(state)
|
||||
template_text = None
|
||||
@@ -2595,12 +2618,16 @@ class ProductSuiteTab(QWidget):
|
||||
state.generation_run_token = run_token
|
||||
state.generation_stop_requested = False
|
||||
state.generation_terminal_streak = 0
|
||||
state.generation_job_ids = []
|
||||
state.generation_mode = "retry" if retrying else "batch"
|
||||
state.generation_retry_job_id = retry_job_id
|
||||
state.done = 0
|
||||
state.failed = 0
|
||||
state.total = len(specs)
|
||||
state.started_at = time.monotonic()
|
||||
state.current_job_ids = []
|
||||
state.show_history = False
|
||||
if not retrying:
|
||||
state.current_job_ids = []
|
||||
state.show_history = False
|
||||
self._generation_run_states[run_token] = state.key
|
||||
worker.progress.connect(self._on_generation_progress_signal)
|
||||
worker.finished.connect(self._on_generation_finished_signal)
|
||||
@@ -2611,17 +2638,27 @@ class ProductSuiteTab(QWidget):
|
||||
state,
|
||||
run_token,
|
||||
"started",
|
||||
{"total": len(specs), "job_ids": 0},
|
||||
{
|
||||
"total": len(specs),
|
||||
"job_ids": 0,
|
||||
"mode": state.generation_mode,
|
||||
},
|
||||
)
|
||||
if state is self._displayed_state:
|
||||
if state is self._displayed_state and not retrying:
|
||||
self._loading = True
|
||||
try:
|
||||
self.history_button.setChecked(False)
|
||||
finally:
|
||||
self._loading = False
|
||||
if state is self._displayed_state:
|
||||
self._apply_running_state(state)
|
||||
self._refresh_results(state)
|
||||
self._status("商品套图生成已开始,共%d张;可切换到其他任务" % len(specs), "info")
|
||||
self._status(
|
||||
"图片重试已开始;可切换到其他任务"
|
||||
if retrying
|
||||
else "商品套图生成已开始,共%d张;可切换到其他任务" % len(specs),
|
||||
"info",
|
||||
)
|
||||
return True
|
||||
|
||||
def _generation_signal_token(self, payload=None):
|
||||
@@ -2651,7 +2688,7 @@ class ProductSuiteTab(QWidget):
|
||||
state.failed = int(payload.get("failed", state.failed) or 0)
|
||||
job_ids = payload.get("job_ids")
|
||||
if job_ids is not None:
|
||||
state.current_job_ids = [int(job_id) for job_id in job_ids]
|
||||
self._set_generation_job_ids(state, job_ids)
|
||||
state.generation_terminal_streak = 0
|
||||
if state is self._displayed_state:
|
||||
self._refresh_results(state)
|
||||
@@ -2670,7 +2707,15 @@ class ProductSuiteTab(QWidget):
|
||||
{"has_error": True},
|
||||
level="ERROR",
|
||||
)
|
||||
self._status("商品套图生成失败:%s" % _user_error(error), "danger")
|
||||
self._status(
|
||||
(
|
||||
"图片重试失败:%s"
|
||||
if state.generation_mode == "retry"
|
||||
else "商品套图生成失败:%s"
|
||||
)
|
||||
% _user_error(error),
|
||||
"danger",
|
||||
)
|
||||
|
||||
@Slot(dict)
|
||||
def _on_generation_finished_signal(self, result):
|
||||
@@ -2678,6 +2723,8 @@ class ProductSuiteTab(QWidget):
|
||||
state = self._generation_state(token)
|
||||
if state is None:
|
||||
return
|
||||
if result.get("job_ids") is not None:
|
||||
self._set_generation_job_ids(state, result.get("job_ids"))
|
||||
self._log_generation_lifecycle(
|
||||
state,
|
||||
token,
|
||||
@@ -2779,7 +2826,7 @@ class ProductSuiteTab(QWidget):
|
||||
)
|
||||
|
||||
def _generation_job_ids(self, state):
|
||||
job_ids = list(state.current_job_ids)
|
||||
job_ids = list(state.generation_job_ids)
|
||||
if not job_ids and state.worker is not None:
|
||||
worker_job_ids = getattr(state.worker, "job_ids", [])
|
||||
if not isinstance(worker_job_ids, (list, tuple, set)):
|
||||
@@ -2789,9 +2836,30 @@ class ProductSuiteTab(QWidget):
|
||||
for job_id in list(worker_job_ids or [])
|
||||
]
|
||||
if job_ids:
|
||||
state.current_job_ids = job_ids
|
||||
self._set_generation_job_ids(state, job_ids)
|
||||
return job_ids
|
||||
|
||||
def _set_generation_job_ids(self, state, job_ids):
|
||||
normalized = []
|
||||
for job_id in job_ids or []:
|
||||
value = int(job_id)
|
||||
if value not in normalized:
|
||||
normalized.append(value)
|
||||
state.generation_job_ids = normalized
|
||||
if state.generation_mode != "retry":
|
||||
state.current_job_ids = list(normalized)
|
||||
return
|
||||
retry_job_id = state.generation_retry_job_id
|
||||
current = [int(job_id) for job_id in state.current_job_ids]
|
||||
if retry_job_id in current:
|
||||
index = current.index(retry_job_id)
|
||||
current[index:index + 1] = normalized
|
||||
elif not state.show_history:
|
||||
for job_id in normalized:
|
||||
if job_id not in current:
|
||||
current.append(job_id)
|
||||
state.current_job_ids = current
|
||||
|
||||
def _generation_job_snapshot(self, state):
|
||||
job_ids = self._generation_job_ids(state)
|
||||
counts = {
|
||||
@@ -2865,6 +2933,7 @@ class ProductSuiteTab(QWidget):
|
||||
def _finalize_generation(self, state, run_token, result, *, source):
|
||||
if self._generation_state(run_token) is not state:
|
||||
return False
|
||||
retrying = state.generation_mode == "retry"
|
||||
snapshot = self._generation_job_snapshot(state)
|
||||
if snapshot["job_ids"] and (
|
||||
snapshot["all_terminal"]
|
||||
@@ -2890,6 +2959,8 @@ class ProductSuiteTab(QWidget):
|
||||
state.generation_run_token = ""
|
||||
state.generation_stop_requested = False
|
||||
state.generation_terminal_streak = 0
|
||||
state.generation_job_ids = []
|
||||
state.generation_retry_job_id = None
|
||||
state.worker = None
|
||||
state.thread = None
|
||||
state.done = success + failed + cancelled
|
||||
@@ -2912,6 +2983,7 @@ class ProductSuiteTab(QWidget):
|
||||
"cancelled": cancelled,
|
||||
"active": active,
|
||||
"elapsed_seconds": elapsed,
|
||||
"mode": "retry" if retrying else "batch",
|
||||
},
|
||||
level="WARNING" if active or result.get("ok") is False else "INFO",
|
||||
)
|
||||
@@ -2923,39 +2995,76 @@ class ProductSuiteTab(QWidget):
|
||||
or "生成线程已结束,部分任务可稍后继续查询"
|
||||
)
|
||||
if state is self._displayed_state:
|
||||
self._message("商品套图生成未完整结束", _user_error(message))
|
||||
self._message(
|
||||
"图片重试未完整结束"
|
||||
if retrying
|
||||
else "商品套图生成未完整结束",
|
||||
_user_error(message),
|
||||
)
|
||||
else:
|
||||
self._status(
|
||||
"套图任务%d生成未完整结束" % state.serial,
|
||||
(
|
||||
"套图任务%d图片重试未完整结束"
|
||||
if retrying
|
||||
else "套图任务%d生成未完整结束"
|
||||
)
|
||||
% state.serial,
|
||||
"danger",
|
||||
)
|
||||
return True
|
||||
if stop_requested or cancelled:
|
||||
if state is self._displayed_state:
|
||||
self._message(
|
||||
"商品套图生成已停止",
|
||||
"本轮共%d张:成功%d张,失败%d张,停止%d张;"
|
||||
"已提交任务可稍后继续查询;总用时%d秒。"
|
||||
% (total, success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
)
|
||||
if retrying:
|
||||
self._message(
|
||||
"图片重试已停止",
|
||||
"本次重试:成功%d张,失败%d张,停止%d张;"
|
||||
"已提交任务可稍后继续查询;总用时%d秒。"
|
||||
% (success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
)
|
||||
else:
|
||||
self._message(
|
||||
"商品套图生成已停止",
|
||||
"本轮共%d张:成功%d张,失败%d张,停止%d张;"
|
||||
"已提交任务可稍后继续查询;总用时%d秒。"
|
||||
% (total, success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
)
|
||||
self._status(
|
||||
"商品套图生成已停止:成功%d张,失败%d张,停止%d张"
|
||||
(
|
||||
"图片重试已停止:成功%d张,失败%d张,停止%d张"
|
||||
if retrying
|
||||
else "商品套图生成已停止:成功%d张,失败%d张,停止%d张"
|
||||
)
|
||||
% (success, failed, cancelled),
|
||||
"warning",
|
||||
)
|
||||
return True
|
||||
if state is self._displayed_state:
|
||||
self._message(
|
||||
"商品套图生成完成",
|
||||
"本轮共%d张:成功%d张,失败%d张,停止%d张;总用时%d秒。"
|
||||
% (total, success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
if retrying:
|
||||
self._message(
|
||||
"图片重试成功" if success and not failed else "图片重试失败",
|
||||
"本次重试:成功%d张,失败%d张,停止%d张;总用时%d秒。"
|
||||
% (success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
)
|
||||
else:
|
||||
self._message(
|
||||
"商品套图生成完成",
|
||||
"本轮共%d张:成功%d张,失败%d张,停止%d张;总用时%d秒。"
|
||||
% (total, success, failed, cancelled, elapsed),
|
||||
icon=QMessageBox.Information,
|
||||
)
|
||||
if retrying:
|
||||
self._status(
|
||||
"图片重试成功" if success and not failed else "图片重试失败,请查看失败卡片",
|
||||
"success" if success and not failed else "danger",
|
||||
)
|
||||
else:
|
||||
self._status(
|
||||
"商品套图生成完成:成功%d张,失败%d张" % (success, failed),
|
||||
"success",
|
||||
)
|
||||
self._status(
|
||||
"商品套图生成完成:成功%d张,失败%d张" % (success, failed),
|
||||
"success",
|
||||
)
|
||||
return True
|
||||
|
||||
def _log_generation_lifecycle(
|
||||
@@ -3012,6 +3121,8 @@ class ProductSuiteTab(QWidget):
|
||||
self.generate_button.setText(
|
||||
"正在停止..."
|
||||
if state.generation_stop_requested
|
||||
else "停止重试"
|
||||
if state.generation_mode == "retry"
|
||||
else "停止生成"
|
||||
)
|
||||
self.generate_button.setStyleSheet(
|
||||
@@ -3035,7 +3146,8 @@ class ProductSuiteTab(QWidget):
|
||||
return
|
||||
elapsed = int(max(0, time.monotonic() - state.started_at)) if state.started_at else 0
|
||||
self.elapsed_label.setText(
|
||||
"套图 %d/%d(%d秒) · 失败 %d" % (
|
||||
"%s %d/%d(%d秒) · 失败 %d" % (
|
||||
"重试" if state.generation_mode == "retry" else "套图",
|
||||
state.done,
|
||||
state.total,
|
||||
elapsed,
|
||||
@@ -3067,8 +3179,12 @@ class ProductSuiteTab(QWidget):
|
||||
return []
|
||||
if state.show_history:
|
||||
return jobs
|
||||
current = set(state.current_job_ids)
|
||||
return [job for job in jobs if int(job.id) in current]
|
||||
by_id = {int(job.id): job for job in jobs}
|
||||
return [
|
||||
by_id[int(job_id)]
|
||||
for job_id in state.current_job_ids
|
||||
if int(job_id) in by_id
|
||||
]
|
||||
|
||||
def _refresh_results(self, state):
|
||||
while self.result_grid.count():
|
||||
@@ -3122,12 +3238,19 @@ class ProductSuiteTab(QWidget):
|
||||
if state.generation_running():
|
||||
self._message("当前任务正在生成", "请等待当前生成结束或停止后再重试单张图片。")
|
||||
return
|
||||
if str(getattr(job, "status", "") or "") not in {
|
||||
"failed",
|
||||
"expired",
|
||||
"cancelled",
|
||||
}:
|
||||
self._status("当前图片无需重试", "warning")
|
||||
return
|
||||
spec = {
|
||||
"source_asset_id": job.source_asset_id,
|
||||
"job_type": job.job_type,
|
||||
"prompt": job.prompt,
|
||||
}
|
||||
self.start_generation(state, specs=[spec])
|
||||
self.start_generation(state, specs=[spec], retry_job_id=job.id)
|
||||
|
||||
def _show_job_menu(self, job, global_position):
|
||||
menu = QMenu(self)
|
||||
|
||||
Reference in New Issue
Block a user