better error traces
This commit is contained in:
@@ -184,8 +184,26 @@ def resolve_no_ready_frames(run: RunState) -> RunStatus:
|
|||||||
):
|
):
|
||||||
return RunStatus.COMPLETED
|
return RunStatus.COMPLETED
|
||||||
if any(frame.status == FrameStatus.BLOCKED for frame in run.frames.values()):
|
if any(frame.status == FrameStatus.BLOCKED for frame in run.frames.values()):
|
||||||
raise WorkflowExecutionError("run has no ready frames and is deadlocked")
|
raise WorkflowExecutionError(
|
||||||
raise WorkflowExecutionError("run has no ready frames")
|
"run has no ready frames and is deadlocked; "
|
||||||
|
f"{_scheduler_state_summary(run)}"
|
||||||
|
)
|
||||||
|
raise WorkflowExecutionError(
|
||||||
|
f"run has no ready frames; {_scheduler_state_summary(run)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _scheduler_state_summary(run: RunState) -> str:
|
||||||
|
"""Return compact scheduler state for no-ready-frame diagnostics."""
|
||||||
|
frame_summary = ", ".join(
|
||||||
|
f"{frame.id}:{frame.status.value}@{frame.node_id}"
|
||||||
|
for frame in run.frames.values()
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"ready_frame_ids={run.ready_frame_ids!r}; "
|
||||||
|
f"current_frame_id={run.current_frame_id!r}; "
|
||||||
|
f"frames=[{frame_summary}]"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _frame(run: RunState, frame_id: str) -> ExecutionFrame:
|
def _frame(run: RunState, frame_id: str) -> ExecutionFrame:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from wf_core.runtime.scheduler import (
|
|||||||
block_frame_on_children,
|
block_frame_on_children,
|
||||||
enqueue_frame,
|
enqueue_frame,
|
||||||
select_next_frame,
|
select_next_frame,
|
||||||
|
resolve_no_ready_frames,
|
||||||
wake_frame,
|
wake_frame,
|
||||||
wake_parent_if_children_complete,
|
wake_parent_if_children_complete,
|
||||||
)
|
)
|
||||||
@@ -162,3 +163,17 @@ def test_resume_wakes_interrupted_frame_at_front() -> None:
|
|||||||
wake_frame(run, "waiting", front=True)
|
wake_frame(run, "waiting", front=True)
|
||||||
|
|
||||||
assert run.ready_frame_ids == ["waiting", "sibling"]
|
assert run.ready_frame_ids == ["waiting", "sibling"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_deadlock_error_includes_ready_queue_and_frame_summary() -> None:
|
||||||
|
run = _run()
|
||||||
|
add_frame(run, ExecutionFrame(id="parent", kind="root", node_id="foreach"))
|
||||||
|
block_frame_on_children(run, "parent", ("missing_child",))
|
||||||
|
|
||||||
|
with pytest.raises(WorkflowExecutionError) as exc_info:
|
||||||
|
resolve_no_ready_frames(run)
|
||||||
|
|
||||||
|
message = str(exc_info.value)
|
||||||
|
assert "deadlocked" in message
|
||||||
|
assert "ready_frame_ids=[]" in message
|
||||||
|
assert "parent:blocked@foreach" in message
|
||||||
|
|||||||
Reference in New Issue
Block a user