71 lines
2.2 KiB
Markdown
71 lines
2.2 KiB
Markdown
# `subscriptions.ts`
|
|
|
|
<!-- begin:auto-docs -->
|
|
_(no submodules)_
|
|
<!-- end:auto-docs -->
|
|
|
|
## 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`
|
|
+ `tenant` pair 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 explicit `close()` accessor.
|
|
- Queues payloads when no consumer is awaiting; resolves immediately when
|
|
a consumer is parked.
|
|
- Calls `GraphqlYogaError("SUBSCRIPTION_TRANSPORT_UNAVAILABLE")` when the
|
|
host hands a `null` broker, satisfying the design doc §10.4 contract.
|
|
|
|
## Usage: Basic
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
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)` — returns
|
|
`AsyncIterable<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.
|