75 lines
3.2 KiB
Python
75 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from biliup_next.app.bootstrap import ensure_initialized
|
|
from biliup_next.app.task_audit import record_task_action
|
|
from biliup_next.app.task_engine import (
|
|
execute_step,
|
|
next_runnable_step,
|
|
)
|
|
from biliup_next.app.task_policies import apply_disabled_step_fallbacks
|
|
from biliup_next.app.task_policies import resolve_failure
|
|
from biliup_next.core.errors import ModuleError
|
|
from biliup_next.core.models import utc_now_iso
|
|
|
|
|
|
def process_task(task_id: str, *, reset_step: str | None = None, include_stage_scan: bool = False) -> dict[str, object]:
|
|
state = ensure_initialized()
|
|
repo = state["repo"]
|
|
task = repo.get_task(task_id)
|
|
if task is None:
|
|
return {"processed": [], "error": {"code": "TASK_NOT_FOUND", "message": f"task not found: {task_id}"}}
|
|
|
|
processed: list[dict[str, object]] = []
|
|
|
|
if include_stage_scan:
|
|
ingest_settings = dict(state["settings"]["ingest"])
|
|
ingest_settings.update(state["settings"]["paths"])
|
|
stage_scan = state["ingest_service"].scan_stage(ingest_settings)
|
|
processed.append({"stage_scan": stage_scan})
|
|
record_task_action(repo, task_id, "stage_scan", "ok", "stage scan completed", stage_scan)
|
|
|
|
if reset_step:
|
|
step_names = {step.step_name for step in repo.list_steps(task_id)}
|
|
if reset_step not in step_names:
|
|
return {"processed": processed, "error": {"code": "STEP_NOT_FOUND", "message": f"step not found: {reset_step}"}}
|
|
repo.update_step_status(
|
|
task_id,
|
|
reset_step,
|
|
"pending",
|
|
error_code=None,
|
|
error_message=None,
|
|
started_at=None,
|
|
finished_at=None,
|
|
)
|
|
repo.update_task_status(task_id, task.status, utc_now_iso())
|
|
processed.append({"task_id": task_id, "step": reset_step, "reset": True})
|
|
record_task_action(repo, task_id, "retry_step", "ok", f"step reset to pending: {reset_step}", {"step_name": reset_step})
|
|
|
|
try:
|
|
while True:
|
|
current_task = repo.get_task(task.id) or task
|
|
current_steps = {step.step_name: step for step in repo.list_steps(task.id)}
|
|
|
|
if apply_disabled_step_fallbacks(state, current_task, repo):
|
|
continue
|
|
|
|
step_name, waiting_payload = next_runnable_step(current_task, current_steps, state)
|
|
if waiting_payload is not None:
|
|
processed.append(waiting_payload)
|
|
return {"processed": processed}
|
|
if step_name is None:
|
|
break
|
|
|
|
payload = execute_step(state, task.id, step_name)
|
|
if current_task.status == "failed_retryable":
|
|
payload["retry"] = True
|
|
record_task_action(repo, task_id, step_name, "ok", f"{step_name} retry succeeded", payload)
|
|
else:
|
|
record_task_action(repo, task_id, step_name, "ok", f"{step_name} succeeded", payload)
|
|
processed.append(payload)
|
|
except ModuleError as exc:
|
|
failure = resolve_failure(task, repo, state, exc)
|
|
processed.append(failure["payload"])
|
|
record_task_action(repo, task_id, failure["step_name"], "error", failure["summary"], failure["payload"])
|
|
return {"processed": processed}
|