EdgeStream
Unsubscribing
Every subscription must be explicitly cleaned up. Leaked subscriptions accumulate, hold closures in memory, and cause stale callback invocations after components are destroyed.
The Unsubscribe Pattern
// 1. Store the subscription handle
const subscription = edgeStream.subscribe('bas', 'workflow.*', handler);
// 2. When done — call unsubscribe()
subscription.unsubscribe();
console.log(subscription.active); // false — removed from SubscriptionManager
In React useEffect
import { useEffect } from 'react';
import { useEdgeStream } from 'edge-stream-js-react';
function WorkflowStatusPanel({ workflowId }: { workflowId: string }) {
const stream = useEdgeStream();
useEffect(() => {
const sub = stream.subscribe(
'bas',
`workflow.${workflowId}.*`,
(envelope) => {
setStatus(envelope.body.status);
}
);
// Cleanup function — React calls this on unmount or when dependencies change
return () => {
sub.unsubscribe();
};
}, [stream, workflowId]);
return <div>...</div>;
}
useSubscription Hook (Automatic Cleanup)
The useSubscription React hook from edge-stream-js-react handles cleanup automatically:
import { useSubscription } from 'edge-stream-js-react';
function WorkflowStatus({ workflowId }: { workflowId: string }) {
// Subscription is automatically removed on unmount
const { isSubscribed, error } = useSubscription(
'bas',
`workflow.${workflowId}.*`,
(envelope) => setStatus(envelope.body.status)
);
if (error) return <div>Error: {error.message}</div>;
return <div>{isSubscribed ? 'Live' : 'Connecting...'}</div>;
}
Multiple Subscriptions Cleanup
// Collect multiple subscription handles
const subscriptions: ISubscription[] = [];
subscriptions.push(stream.subscribe('bas', 'workflow.*', workflowHandler));
subscriptions.push(stream.subscribe('bas', 'agent.*', agentHandler));
subscriptions.push(stream.subscribe('bas', 'notifications.*', notifHandler));
// Cleanup all at once
function cleanup() {
subscriptions.forEach(sub => sub.unsubscribe());
subscriptions.length = 0;
}
clear() — Emergency Cleanup
In tests or on full teardown, use subscriptionManager.clear() to remove all subscriptions at once:
// Test teardown
afterEach(() => {
edgeStream.server('bas')!.subscriptionManager.clear();
});
// Application teardown
await edgeStream.stop();
// stop() cleans up transports; subscriptions should be cleaned separately
Subscription Leaks
Subscribing in a React component's render body (without useEffect) creates a new subscription on every render. After 100 renders, you have 100 active subscriptions calling the same handler. Always use
useEffect with a cleanup function, or use the useSubscription hook.