Flow Studio
Observer SignalR Hook
useFlowObserverSignalR is the Observer Panel's own SignalR connection — independent from the designer's useExecutionSignalR. This separation allows the Observer Panel to be embedded outside the designer while still receiving real-time execution events.
Why a Separate Hook?
The designer's useExecutionSignalR hook manages the canvas-level connection — updating node border colours, triggering re-renders on the React Flow canvas. The Observer Panel has different needs:
- It may be mounted separately from the designer (e.g., in a monitoring dashboard)
- It manages its own log buffer, node status list, and tab state
- It can operate independently when the designer is not open
In practice, when both are mounted together (the normal case), both hooks connect to the same SignalR hub and the same execution group. The server broadcasts to all group members, so both receive every event.
useFlowObserverSignalR
// flow-observer-core/src/hooks/useFlowObserverSignalR.ts
export function useFlowObserverSignalR(executionId: string) {
const engine = useFlowObserverPanelEngine();
const store = useFlowObserverPanelStore();
useEffect(() => {
const connection = new HubConnectionBuilder()
.withUrl('/hubs/execution', {
accessTokenFactory: () => getAuthToken()
})
.withAutomaticReconnect([1000, 2000, 5000, 10000])
.build();
connection.on('ExecutionEvent', (event: ExecutionEvent) => {
// Route all events through the engine
engine.pushExecutionEvent(event);
// Also update store directly for status/progress
if (event.type === 'WorkflowExecutionCompleted') {
store.setStatus(event.status);
}
if (event.type === 'NodeExecutionCompleted') {
store.incrementCompletedCount();
}
});
connection.start()
.then(() => connection.invoke('JoinExecutionGroup', executionId));
return () => { connection.stop(); };
}, [executionId]);
}
Connection Relationship Diagram
| Hook | Consumer | Purpose |
|---|---|---|
useExecutionSignalR | Designer canvas | Update node border colours and canvas execution overlays |
useFlowObserverSignalR | Observer Panel | Feed log buffer, node list, status tab, Node Inspector |
Two Connections, Same Group
When both hooks are active, the browser maintains two separate WebSocket connections to
/hubs/execution. Both join the same execution group. This is expected behaviour — SignalR groups are broadcast-based, so the server sends each event once to the group and both connections receive it. There is no duplication of events in the stores because each hook writes to a different store (designerModeStore vs flowObserverPanelStore).