EdgeStream
Multiple Transports
Each EdgeStream server has exactly one transport. To use multiple transports — for example, SignalR for workflow events and WebSocket for agent streaming — register multiple servers, each with its own transport configuration.
One Transport Per Server
The architecture is: EdgeStream → Servers → Transport. Each server owns one transport. Multiple servers = multiple transports, all managed by a single EdgeStream instance:
EdgeStream
├── Server 'bas' → SignalRTransport (/hubs/edge-stream)
├── Server 'chat' → RawWebSocketTransport (wss://chat.bizfirst.com/ws)
└── Server 'audit' → SseTransport (/api/audit/stream)
Registering Multiple Transports
const stream = createEdgeStream({ logLevel: 'info' });
// Transport 1: SignalR for workflow + HIL events
stream.registerServer({
id: 'bas',
type: 'bas',
url: '/hubs/edge-stream',
transportConfig: {
type: 'signalr',
url: '/hubs/edge-stream',
accessToken: authStore.getToken(),
}
});
// Transport 2: Raw WebSocket for Octopus agent streaming (low latency)
stream.registerServer({
id: 'chat',
type: 'chat',
url: 'wss://chat.bizfirst.com/ws',
transportConfig: {
type: 'websocket',
url: 'wss://chat.bizfirst.com/ws',
queryParams: { token: authStore.getChatToken() },
}
});
// Transport 3: SSE for read-only audit stream
stream.registerServer({
id: 'audit',
type: 'bas',
url: '/api/audit/stream',
transportConfig: {
type: 'sse',
url: '/api/audit/stream',
queryParams: { tenantId: tenantId },
}
});
// All three connect concurrently
await stream.start();
Subscribing per Transport
// Subscribe to workflow events (SignalR)
stream.subscribe('bas', 'workflow.*', workflowHandler);
stream.subscribe('bas', 'hil.*', hilHandler);
// Subscribe to agent streaming (WebSocket)
stream.subscribe('chat', 'agent.chat.*', chatHandler);
// Subscribe to audit events (SSE — receive only)
stream.subscribe('audit', 'audit.*', auditHandler);
Monitoring Transport Status Independently
// Monitor each transport independently
const basTransport = stream.server('bas')!.transport;
const chatTransport = stream.server('chat')!.transport;
basTransport.onStatusChange((status) => {
uiStore.setBASStatus(status); // 'connected' | 'reconnecting' | ...
});
chatTransport.onStatusChange((status) => {
uiStore.setChatStatus(status);
});
// Or use EdgeStream lifecycle events (server-level)
stream.on('server:connected', (event) => {
console.log(`${event.serverId} transport connected`);
// event.serverId is 'bas', 'chat', or 'audit'
});
stream.on('server:disconnected', (event) => {
console.warn(`${event.serverId} transport disconnected`);
});
Transport Isolation
Each server's transport is fully isolated from others. A reconnecting WebSocket does not affect the SignalR connection:
| Event | Affected | Unaffected |
|---|---|---|
| Chat WebSocket drops | Server 'chat' → reconnecting | Server 'bas' (SignalR) continues normally |
| BAS SignalR error | Server 'bas' → error | Server 'chat', Server 'audit' unaffected |
| stream.stop() | ALL servers disconnected concurrently | N/A |
start() and stop() Are Global
stream.start() connects ALL registered servers concurrently via Promise.all. stream.stop() disconnects ALL servers concurrently. To connect/disconnect a single server independently, call server.start() or server.stop() directly on the server reference.
Next: Observability
Learn how to monitor hook activity, subscriber delivery, and pipeline health in real-time using EdgeStream's observability hooks. See Guide 7: Observability.