first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# `event-buffer`
## Purpose
Provides the per-`(tenant, topic)` reconnect-event buffer used to replay events to a reconnecting client whose `lastEventId` precedes the current head. Two concrete implementations ship — `MemoryReconnectEventBuffer` for single-host deployments and `BrokerReconnectEventBuffer` for broker-backed multi-host fan-out — and `resolveReconnectEventBuffer` picks the right one according to the configured strategy and the broker wired into the host.
This module is the operating-default pin for design doc §14 open question on buffer storage: the foundation ships `"auto"` which resolves to broker-backed when a Redis broker is wired, in-memory otherwise.
## Features
- Strategy enum (`"auto" | "memory" | "broker"`) with three documented behaviours.
- `MemoryReconnectEventBuffer` is a per-bucket ring buffer — FIFO eviction, `limit` events per `(tenant, topic)` pair.
- `BrokerReconnectEventBuffer` maintains a local mirror so replay still works during transient broker downtime; pushes also flow to the broker on a fire-and-forget topic for peer-host mirrors.
- `"broker"` strategy refuses boot with `WS_BUN.RECONNECT_BUFFER_MISS` when no buffer-capable broker is wired.
## Usage: Basic
```ts
import { MemoryReconnectEventBuffer } from "@suaveplan/api-ws-bun";
const buf = new MemoryReconnectEventBuffer<{ value: number }>(64);
buf.push({ id: "1", topic: "orders", tenant, payload: { value: 1 } });
buf.push({ id: "2", topic: "orders", tenant, payload: { value: 2 } });
const replay = buf.since(tenant, "orders", "1");
console.log(replay.length); // 1
```
## Usage: Advanced
```ts
import {
resolveReconnectEventBuffer,
isBufferCapableBroker,
} from "@suaveplan/api-ws-bun";
const buffer = resolveReconnectEventBuffer("auto", broker, 256);
// If `broker.supportsReconnectBuffer === true`, returns a
// BrokerReconnectEventBuffer wrapping `broker`. Otherwise returns
// MemoryReconnectEventBuffer.
console.log(isBufferCapableBroker(broker)); // true | false
```
## API Reference
- `BufferedEvent<Payload>` — `{ id, topic, tenant, payload }`.
- `ReconnectEventBuffer<Payload>` — `{ push, since, dispose }`.
- `BufferCapableBroker<Payload>` — broker contract extension flagging buffer support.
- `isBufferCapableBroker(broker): boolean` — discriminant.
- `MemoryReconnectEventBuffer<Payload>` — single-host implementation.
- `BrokerReconnectEventBuffer<Payload>` — broker-backed wrapper.
- `resolveReconnectEventBuffer(strategy, broker, limit)` — factory.
## Implementation Notes
The memory buffer uses `Array.prototype.shift()` for eviction because the typical `limit` is small (default 256 events per `(tenant, topic)` pair), so the O(n) shift is dwarfed by the network cost of a single broadcast. A linked-list ring would micro-optimise the eviction at the cost of opaqueness; the simple array form keeps the code one screenful tall.
The broker wrapper performs `void this.broker.publish(...)` rather than awaiting because the buffer's contract guarantees `push` is synchronous — the caller is on the broadcast hot-path and cannot block on broker latency. Peer-host mirror sync is therefore best-effort; deployments that need strict mirror consistency configure `"broker"` against a stronger backend.