first commit
This commit is contained in:
108
docs/api-stack/api/api-sse-bun/src/engine/bun-sse-engine.md
Normal file
108
docs/api-stack/api/api-sse-bun/src/engine/bun-sse-engine.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# `bun-sse-engine`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The `bun-sse-engine` module exports `createBunSseEngine`, the factory
|
||||
the host calls to mount Server-Sent Events on top of `Bun.serve`. The
|
||||
factory wires the seven collaborators (options, subscription bus,
|
||||
tenant cap, event buffer, instruments, handshake pipeline, active
|
||||
connection registry) into one cohesive engine value. Plugin authors
|
||||
never touch the internals — they hand the engine to the host's router
|
||||
which calls `engine.acceptRequest(...)` on every matching GET request.
|
||||
|
||||
## Features
|
||||
|
||||
- Single factory: validated options, broker- or in-memory event buffer
|
||||
selected automatically, shared subscription bus exposed for the WS
|
||||
engine to plug into.
|
||||
- `acceptRequest({ request, path, topic })` runs the full handshake
|
||||
pipeline and returns the 200 streaming `Response`.
|
||||
- `publish(envelope)` shortcut: append to the buffer + broadcast on the
|
||||
bus in one call — used by plugins that publish in-process.
|
||||
- `activeConnections` map for observability dashboards (size, tenant
|
||||
distribution, oldest open).
|
||||
- `buildReplayBuffer` exposed for the conformance harness so the
|
||||
engine's ring-buffer semantics are pinned by the same test path
|
||||
every other engine uses.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { createBunSseEngine } from "@suaveplan/api-sse-bun";
|
||||
|
||||
const engine = createBunSseEngine({
|
||||
authenticate: async () => ({
|
||||
tenantId: "acme" as never,
|
||||
principal: null,
|
||||
}),
|
||||
});
|
||||
// ...wire engine.acceptRequest into a Bun.serve handler...
|
||||
engine.dispose();
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { createBunSseEngine } from "@suaveplan/api-sse-bun";
|
||||
import Bun from "bun";
|
||||
|
||||
const engine = createBunSseEngine({
|
||||
eventBufferSize: 512,
|
||||
eventBufferMs: 600_000,
|
||||
keepAliveCommentMs: 30_000,
|
||||
maxConnectionsPerTenant: 5_000,
|
||||
compressionEnabled: true,
|
||||
retryMs: 4_000,
|
||||
authenticate: async (req) => {
|
||||
const tenant = req.headers.get("x-tenant");
|
||||
if (tenant === null) return { tenantId: null, principal: null };
|
||||
return { tenantId: tenant as never, principal: null };
|
||||
},
|
||||
});
|
||||
|
||||
Bun.serve({
|
||||
port: 0,
|
||||
async fetch(request) {
|
||||
const url = new URL(request.url);
|
||||
if (url.pathname === "/sse/audit") {
|
||||
return engine.acceptRequest({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
url: request.url,
|
||||
method: request.method,
|
||||
},
|
||||
path: url.pathname,
|
||||
topic: "audit",
|
||||
});
|
||||
}
|
||||
return new Response("not found", { status: 404 });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interface SseAcceptInputs` — `{ request, path, topic }`.
|
||||
- `interface BunSseEngine` — `bus`, `cap`, `buffer`, `instruments`,
|
||||
`options`, `activeConnections`, `acceptRequest(inputs)`,
|
||||
`publish(envelope)`, `dispose()`, `buildReplayBuffer(opts?)`.
|
||||
- `function createBunSseEngine(options: BunSseEngineOptions): BunSseEngine`.
|
||||
- `function aggregateConnectionSnapshot(active, plugin): readonly { plugin,
|
||||
path, tenant, value }[]` — exported so OTel snapshots can be exercised
|
||||
in tests independent of the global meter provider.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The factory does not start any background timers — every long-lived
|
||||
resource (keep-alive scheduler, gzip stream) is owned by the
|
||||
handshake pipeline and bound to a single connection. `dispose()` is a
|
||||
synchronous best-effort: it cancels the bus and clears the active map
|
||||
but does not eagerly close every open stream (the HTTP transport
|
||||
handles that when the underlying socket closes). The
|
||||
`connectionSnapshot` for the OTel gauge aggregates active connections
|
||||
per `(path, tenantId)` so dashboards can plot capacity per route per
|
||||
tenant without re-walking the connection set inside the SDK callback.
|
||||
Reference in New Issue
Block a user