Portal Community

useExecutionSignalR

// useExecutionSignalR.ts (simplified)
export function useExecutionSignalR(executionId: string) {
  const connectionRef = useRef<HubConnection | null>(null);

  useEffect(() => {
    const connection = new HubConnectionBuilder()
      .withUrl('/hubs/execution', {
        accessTokenFactory: () => getAuthToken()  // JWT
      })
      .withAutomaticReconnect([1000, 2000, 5000, 10000])
      .build();

    connection.start().then(() => {
      connection.invoke('JoinExecution', executionId);
    });

    // Register event handlers
    connection.on('NodeExecutionStarted', handleNodeStarted);
    connection.on('NodeExecutionCompleted', handleNodeCompleted);
    connection.on('NodeExecutionFailed', handleNodeFailed);
    connection.on('WorkflowExecutionCompleted', handleWorkflowCompleted);

    connectionRef.current = connection;

    // Cleanup on unmount or executionId change
    return () => {
      connection.invoke('LeaveExecution', executionId);
      connection.stop();
    };
  }, [executionId]);
}

Authentication

The SignalR connection includes the user's JWT bearer token via the accessTokenFactory. The backend hub validates the token on connection. If the token expires during a long execution, SignalR automatically reconnects with a fresh token.

Hub URL and Transport

SettingValue
Hub URL/hubs/execution
Preferred transportWebSocket
Fallback transportsServer-Sent Events, then Long-Polling
Reconnect delays1s, 2s, 5s, 10s (then gives up and falls back to polling)

Connection States

StateMeaningUI Indicator
ConnectingWebSocket handshake in progressSpinner in Observer Panel header
ConnectedWebSocket open and subscribedGreen dot in Observer Panel header
ReconnectingConnection lost; attempting to restoreAmber dot + "Reconnecting..."
DisconnectedConnection lost permanently; polling fallback activeRed dot + "Live updates unavailable"