2.2 KiB
subscriptions.ts
(no submodules)
Purpose
Bridges the WsBroker contract from @suaveplan/api-ws to GraphQL
Subscription resolvers via AsyncIterable<Payload>. The Yoga engine
wires graphql-ws over the host's already-mounted WebSocket transport;
this module is the per-subscription helper that converts a broker topic
tenantpair into an iterator the engine can consume.
Tenant filtering is enforced at the bridge: only BrokerEnvelope items
whose tenant === tenantArg reach the GraphQL iterator. Closing the
iterator (return() or the explicit close() method) calls
subscription.unsubscribe() on the broker so the WS slot is released
within one tick.
Features
- Returns
AsyncIterable<Payload>with an explicitclose()accessor. - Queues payloads when no consumer is awaiting; resolves immediately when a consumer is parked.
- Calls
GraphqlYogaError("SUBSCRIPTION_TRANSPORT_UNAVAILABLE")when the host hands anullbroker, satisfying the design doc §10.4 contract.
Usage: Basic
import { createInMemoryWsBroker } from "@suaveplan/api-ws-broker-in-memory";
import { subscribeBrokerTopic } from "@suaveplan/api-graphql-yoga";
const broker = createInMemoryWsBroker();
const iterable = subscribeBrokerTopic(
broker,
"billing.invoice.created",
"tenant-a" as never
);
for await (const event of iterable) {
console.log(event);
break;
}
await iterable.close();
Usage: Advanced
import { subscribeBrokerTopic } from "@suaveplan/api-graphql-yoga";
const subscription = {
invoiceCreated(_parent: unknown, _args: unknown, ctx: { broker: never; tenantId: never }) {
return subscribeBrokerTopic(ctx.broker, "billing.invoice.created", ctx.tenantId);
},
};
API Reference
subscribeBrokerTopic(broker, topic, tenant)— returnsAsyncIterable<Payload> & { close(): Promise<void> }.
Implementation Notes
The internal queue + waiters arrays form a simple bounded mailbox.
Backpressure (queue cap, drop oldest, etc.) is intentionally not modelled
here — the in-memory broker enforces its own bounds, and the Redis broker
will inherit the same back-end contract.