feat: include failed step in task errors
This commit is contained in:
@@ -553,7 +553,7 @@ def generate_batch(tasks, prompts, ai_cfg=None, on_progress=None, should_stop=No
|
||||
summary["failed"] += 1
|
||||
summary["ok"] = False
|
||||
step = get_step(task, "title_request")
|
||||
error = _mark_generate_failed(task, exc, db_path, on_task_update)
|
||||
error = _mark_generate_failed(task, exc, db_path, on_task_update, step=step)
|
||||
_emit_generation_event(on_event, task, "title", step, "failed", detail=error, level="error")
|
||||
_emit_generation_error(on_error, task, "title", step, exc, error)
|
||||
_emit_generation_progress(on_progress, summary)
|
||||
@@ -590,7 +590,7 @@ def generate_batch(tasks, prompts, ai_cfg=None, on_progress=None, should_stop=No
|
||||
summary["failed"] += 1
|
||||
summary["ok"] = False
|
||||
step = get_step(task, fallback_step)
|
||||
error = _mark_generate_failed(task, exc, db_path, on_task_update)
|
||||
error = _mark_generate_failed(task, exc, db_path, on_task_update, step=step)
|
||||
_emit_generation_event(on_event, task, "cover", step, "failed", detail=error, level="error")
|
||||
_emit_generation_error(on_error, task, "cover", step, exc, error)
|
||||
|
||||
@@ -1654,9 +1654,10 @@ def _new_cover_path(task, account_by_alias, image_root):
|
||||
return image_paths.task_image_path(image_root, task, account, "new")
|
||||
|
||||
|
||||
def _mark_generate_failed(task, exc, db_path, on_task_update):
|
||||
def _mark_generate_failed(task, exc, db_path, on_task_update, step=None):
|
||||
error = diagnostics.redact_log_text(str(exc) or exc.__class__.__name__)
|
||||
db.mark_failed(task.id, "generate", error, path=db_path)
|
||||
error = db.format_failure_error(error, step)
|
||||
db.mark_failed(task.id, "generate", error, path=db_path, step=step)
|
||||
if on_task_update is not None:
|
||||
on_task_update(task.id, {"status": "failed", "last_error": error})
|
||||
return error
|
||||
|
||||
@@ -23,6 +23,37 @@ VALID_BATCH_FIELDS = {
|
||||
"deleted_at",
|
||||
"deleted_reason",
|
||||
}
|
||||
FAILURE_STEP_LABELS = {
|
||||
"preflight": "预检",
|
||||
"check_chrome": "检查Chrome",
|
||||
"login_check": "检测登录",
|
||||
"open_product": "打开商品页",
|
||||
"wait_ready": "页面就绪",
|
||||
"read_title": "读标题",
|
||||
"read_cover": "读封面",
|
||||
"download_cover": "下载封面",
|
||||
"db_write": "写库",
|
||||
"excel_write_back": "回写Excel",
|
||||
"write_excel": "回写Excel",
|
||||
"load_text_model": "加载文本模型",
|
||||
"title_submit": "提交标题任务",
|
||||
"title_build_request": "构建标题请求",
|
||||
"title_request": "请求生成标题",
|
||||
"title_parse_response": "解析标题响应",
|
||||
"load_image_model": "加载图片模型",
|
||||
"cover_validate_input": "校验旧封面",
|
||||
"cover_prompt_render": "渲染封面提示词",
|
||||
"cover_submit": "提交封面任务",
|
||||
"cover_build_request": "构建封面请求",
|
||||
"cover_request": "请求生成封面",
|
||||
"cover_download": "下载新封面",
|
||||
"cover_save": "保存新封面",
|
||||
"cover_parse_response": "解析封面响应",
|
||||
"apply_task": "更新商品",
|
||||
"change_title": "修改标题",
|
||||
"replace_cover": "更新封面",
|
||||
"click_update": "点击更新",
|
||||
}
|
||||
VALID_ACCOUNT_FIELDS = {
|
||||
"account_name",
|
||||
"alias",
|
||||
@@ -607,8 +638,28 @@ def mark_running(task_id, phase, path=None, conn=None) -> None:
|
||||
)
|
||||
|
||||
|
||||
def mark_failed(task_id, phase, error, path=None, conn=None) -> None:
|
||||
def failure_step_label(step):
|
||||
value = str(step or "").strip()
|
||||
return FAILURE_STEP_LABELS.get(value, value)
|
||||
|
||||
|
||||
def format_failure_error(error, step=None):
|
||||
message = str(error or "")
|
||||
label = failure_step_label(step)
|
||||
if not label:
|
||||
return message
|
||||
prefix = f"{label}失败:"
|
||||
if message.startswith(prefix):
|
||||
return message
|
||||
for known_label in FAILURE_STEP_LABELS.values():
|
||||
if message.startswith(f"{known_label}失败:") or message.startswith(f"{known_label}失败:"):
|
||||
return message
|
||||
return prefix + message
|
||||
|
||||
|
||||
def mark_failed(task_id, phase, error, path=None, conn=None, step=None) -> None:
|
||||
attempt_field = _attempt_field(phase)
|
||||
formatted_error = format_failure_error(error, step)
|
||||
with _connection(conn, path) as database:
|
||||
with database:
|
||||
database.execute(
|
||||
@@ -620,7 +671,7 @@ def mark_failed(task_id, phase, error, path=None, conn=None) -> None:
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
""",
|
||||
(str(error), _now(), int(task_id)),
|
||||
(formatted_error, _now(), int(task_id)),
|
||||
)
|
||||
|
||||
|
||||
@@ -708,7 +759,7 @@ def update_generated_title(task_id, new_title, path=None, conn=None) -> None:
|
||||
(title, now, int(task_id)),
|
||||
)
|
||||
|
||||
def set_applied(task_id, committed, error=None, path=None, conn=None) -> None:
|
||||
def set_applied(task_id, committed, error=None, path=None, conn=None, step=None) -> None:
|
||||
now = _now()
|
||||
success = bool(committed) and error is None
|
||||
with _connection(conn, path) as database:
|
||||
@@ -729,6 +780,7 @@ def set_applied(task_id, committed, error=None, path=None, conn=None) -> None:
|
||||
(now, now, int(task_id)),
|
||||
)
|
||||
else:
|
||||
formatted_error = format_failure_error(error or "未提交更新", step)
|
||||
database.execute(
|
||||
"""
|
||||
UPDATE tasks
|
||||
@@ -739,7 +791,7 @@ def set_applied(task_id, committed, error=None, path=None, conn=None) -> None:
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
""",
|
||||
(str(error or "未提交更新"), now, int(task_id)),
|
||||
(formatted_error, now, int(task_id)),
|
||||
)
|
||||
|
||||
|
||||
|
||||
+14
-10
@@ -792,6 +792,7 @@ class ApplyWorker(BaseWorker):
|
||||
)
|
||||
db.mark_running(task.id, "apply", path=self.db_path)
|
||||
self.row_updated.emit(task.id, {"status": "running", "last_error": None})
|
||||
current_step = "apply_task"
|
||||
result = editor.apply_task(
|
||||
account,
|
||||
task,
|
||||
@@ -800,6 +801,7 @@ class ApplyWorker(BaseWorker):
|
||||
)
|
||||
committed = bool(result.get("committed")) and not result.get("error")
|
||||
error = result.get("error")
|
||||
failed_step = self._failed_apply_step(result, current_step)
|
||||
current_step = "db_write"
|
||||
self._log_run_event(
|
||||
f"step=db_write result=start detail=任务 {task.id} 商品 {task.item_id} 保存更新结果",
|
||||
@@ -824,13 +826,13 @@ class ApplyWorker(BaseWorker):
|
||||
return "applied"
|
||||
|
||||
error = diagnostics.redact_log_text(error or "更新未提交")
|
||||
failed_step = self._failed_apply_step(result, current_step)
|
||||
db.set_applied(task.id, False, error, path=self.db_path)
|
||||
display_error = db.format_failure_error(error, failed_step)
|
||||
db.set_applied(task.id, False, error, path=self.db_path, step=failed_step)
|
||||
elapsed_ms = self._elapsed_ms(started)
|
||||
self.failed.emit(task.id, str(error))
|
||||
self.failed.emit(task.id, str(display_error))
|
||||
self.row_updated.emit(
|
||||
task.id,
|
||||
{"status": "failed", "last_error": str(error), "committed": 0},
|
||||
{"status": "failed", "last_error": str(display_error), "committed": 0},
|
||||
)
|
||||
self._log_run_event(
|
||||
f"step={failed_step} result=failed detail={error} elapsed_ms={elapsed_ms}",
|
||||
@@ -852,12 +854,13 @@ class ApplyWorker(BaseWorker):
|
||||
return "failed"
|
||||
except Exception as exc:
|
||||
error = diagnostics.redact_log_text(str(exc) or exc.__class__.__name__)
|
||||
db.set_applied(task.id, False, error, path=self.db_path)
|
||||
display_error = db.format_failure_error(error, current_step)
|
||||
db.set_applied(task.id, False, error, path=self.db_path, step=current_step)
|
||||
elapsed_ms = self._elapsed_ms(started)
|
||||
self.failed.emit(task.id, error)
|
||||
self.failed.emit(task.id, display_error)
|
||||
self.row_updated.emit(
|
||||
task.id,
|
||||
{"status": "failed", "last_error": error, "committed": 0},
|
||||
{"status": "failed", "last_error": display_error, "committed": 0},
|
||||
)
|
||||
self._log_run_event(
|
||||
f"step={current_step} result=failed detail={error} elapsed_ms={elapsed_ms}",
|
||||
@@ -1259,10 +1262,11 @@ class CollectWorker(BaseWorker):
|
||||
failed += 1
|
||||
error = str(exc) or exc.__class__.__name__
|
||||
safe_error = diagnostics.redact_log_text(error)
|
||||
display_error = db.format_failure_error(safe_error, current_step)
|
||||
elapsed_ms = self._elapsed_ms(started)
|
||||
db.mark_failed(task.id, "collect", safe_error, path=self.db_path)
|
||||
self.failed.emit(task.id, safe_error)
|
||||
self.row_updated.emit(task.id, {"status": "failed", "last_error": safe_error})
|
||||
db.mark_failed(task.id, "collect", safe_error, path=self.db_path, step=current_step)
|
||||
self.failed.emit(task.id, display_error)
|
||||
self.row_updated.emit(task.id, {"status": "failed", "last_error": display_error})
|
||||
self._log_run_event(
|
||||
"step={step} result=failed detail={error} elapsed_ms={elapsed_ms}".format(
|
||||
step=current_step,
|
||||
|
||||
Reference in New Issue
Block a user