feat: add workflow run dispatch foundation

This commit is contained in:
2026-04-07 10:11:46 +02:00
parent ab1b220e79
commit 6ad34ceed2
7 changed files with 548 additions and 54 deletions
@@ -200,6 +200,9 @@ async def list_workflow_runs(
class WorkflowDispatchResponse(BaseModel):
workflow_run: WorkflowRunOut
context_id: str
execution_mode: str
dispatched: int
task_ids: list[str]
@@ -225,7 +228,15 @@ async def dispatch_workflow_endpoint(
the caller can track progress.
"""
from pydantic import ValidationError as _ValidationError
from app.domains.rendering.workflow_executor import dispatch_workflow
from app.domains.rendering.workflow_executor import (
dispatch_prepared_workflow,
prepare_workflow_context,
)
from app.domains.rendering.workflow_run_service import (
apply_graph_dispatch_result,
create_workflow_run,
mark_workflow_run_failed,
)
result = await db.execute(
select(WorkflowDefinition).where(WorkflowDefinition.id == workflow_id)
@@ -237,10 +248,59 @@ async def dispatch_workflow_endpoint(
raise HTTPException(status_code=400, detail="Workflow has no config")
try:
task_ids = dispatch_workflow(wf.config, context_id)
workflow_context = prepare_workflow_context(
wf.config,
context_id=context_id,
execution_mode="graph",
)
except _ValidationError as exc:
raise HTTPException(status_code=422, detail=f"Invalid workflow config: {exc.errors()}")
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc))
return WorkflowDispatchResponse(dispatched=len(task_ids), task_ids=task_ids)
run_id = await db.run_sync(
lambda sync_session: create_workflow_run(
sync_session,
workflow_def_id=wf.id,
order_line_id=None,
workflow_context=workflow_context,
).id
)
await db.commit()
try:
dispatch_result = dispatch_prepared_workflow(workflow_context)
except Exception as exc:
failed_result = await db.execute(
select(WorkflowRun)
.where(WorkflowRun.id == run_id)
.options(selectinload(WorkflowRun.node_results))
)
failed_run = failed_result.scalar_one()
mark_workflow_run_failed(failed_run, str(exc))
await db.commit()
raise
run_result = await db.execute(
select(WorkflowRun)
.where(WorkflowRun.id == run_id)
.options(selectinload(WorkflowRun.node_results))
)
run = run_result.scalar_one()
apply_graph_dispatch_result(run, workflow_context, dispatch_result)
await db.commit()
refreshed_result = await db.execute(
select(WorkflowRun)
.where(WorkflowRun.id == run_id)
.options(selectinload(WorkflowRun.node_results))
)
refreshed_run = refreshed_result.scalar_one()
return WorkflowDispatchResponse(
workflow_run=refreshed_run,
context_id=context_id,
execution_mode=workflow_context.execution_mode,
dispatched=len(dispatch_result.task_ids),
task_ids=dispatch_result.task_ids,
)