Workflow Execution Visualization
When a workflow designed on the canvas actually runs, we needed to visually show which nodes are currently being processed and where errors have occurred. This post covers the integration between the workflow execution engine and the frontend.
Modeling Execution State
We started by clearly defining the execution state for each node.
type NodeExecutionStatus =
| 'idle' // 대기 중
| 'pending' // 실행 대기열
| 'running' // 실행 중
| 'completed' // 완료
| 'error' // 에러 발생
| 'skipped'; // 조건부 스킵
interface WorkflowExecution {
id: string;
status: 'running' | 'completed' | 'failed';
nodeStatuses: Record<string, NodeExecutionStatus>;
nodeOutputs: Record<string, unknown>;
startedAt: Date;
completedAt?: Date;
}
Highlighting Active Nodes
When a workflow runs, each node receives a status-specific style. A running node pulses with a blue animated border, completed nodes turn green, and error nodes turn red.
/* 노드 실행 상태 스타일 */
.node-running {
border-color: #3b82f6;
animation: pulse 1.5s ease-in-out infinite;
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
}
.node-completed {
border-color: #22c55e;
}
.node-error {
border-color: #ef4444;
box-shadow: 0 0 20px rgba(239, 68, 68, 0.3);
}
Streaming Execution State via SSE
The backend streams each node's execution progress over SSE. The frontend subscribes to this stream and reflects updates on the canvas in real time.
function useWorkflowExecution(executionId: string) {
const updateNodeStatus = useCanvasStore((s) => s.updateNodeStatus);
useEffect(() => {
const eventSource = new EventSource(
`/api/execution/${executionId}/stream`
);
eventSource.addEventListener('node_start', (e) => {
const data = JSON.parse(e.data);
updateNodeStatus(data.nodeId, 'running');
});
eventSource.addEventListener('node_complete', (e) => {
const data = JSON.parse(e.data);
updateNodeStatus(data.nodeId, 'completed');
});
eventSource.addEventListener('node_error', (e) => {
const data = JSON.parse(e.data);
updateNodeStatus(data.nodeId, 'error');
});
return () => eventSource.close();
}, [executionId]);
}
Execution Results Panel
Once a workflow completes, a panel lets users inspect the input and output data for each node. Clicking a node opens a side panel showing that node's execution log, elapsed time, and I/O data.
Re-runs and Partial Execution
Beyond re-running the entire workflow, we also implemented the ability to re-run from a specific node. Right-clicking a node on the canvas reveals a "Run from here" option. This turned out to be extremely useful during debugging.