Flow Studio
Node Statuses in executionStore
executionStore.nodeStatuses is a Record keyed by nodeId holding the current execution status of each node. SignalR events update individual entries in place — only the changed node triggers a re-render in subscribing components.
How SignalR Updates Flow In
// useExecutionSignalR.ts
connection.on("NodeStatusChanged", (event: NodeStatusChangedEvent) => {
// Update executionStore (for Observer Panel tabs)
useExecutionStore.getState().setNodeStatus(event.nodeId, {
nodeId : event.nodeId,
status : event.status,
startedAt : event.startedAt,
completedAt : event.completedAt,
durationMs : event.durationMs,
errorMessage: event.errorMessage,
retryCount : event.retryCount
});
// Also update designerModeStore (for canvas overlays)
useDesignerModeStore.getState().setNodeStatus(event.nodeId, event);
});
setNodeStatus Implementation
setNodeStatus: (nodeId, status) => set(state => ({
nodeStatuses: {
...state.nodeStatuses,
[nodeId]: status
}
}));
// Immutable update — creates a new object for nodeStatuses
// Only components subscribing to state.nodeStatuses[specificNodeId] re-render
Consuming Node Statuses in the Nodes Tab
// NodeListTabContent.tsx — shows all nodes with their statuses
function NodeListTabContent() {
const nodeStatuses = useExecutionStore(state => state.nodeStatuses);
const { nodes } = useWorkflowStore(state => ({ nodes: state.nodes }));
return (
<ul>
{nodes.map(node => {
const status = nodeStatuses[node.id];
return (
<li key={node.id}>
<StatusDot status={status?.status ?? 'pending'} />
<span>{node.data.label}</span>
{status?.durationMs != null &&
<span>{status.durationMs}ms</span>}
</li>
);
})}
</ul>
);
}
nodeStatuses is the Observer Panel view — not the authority. The authoritative status lives in the backend
Process_Executions table. The frontend store is a real-time mirror. If a user reloads mid-execution, the statuses are re-fetched from the API.