Portal Community

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.