Update peer dep from @rayhanadev/iroh to @alkdev/iroh. Document platform strategy: Linux native + WASM fallback, Windows/macOS deferred. Fix outdated single-import reference in iroh-transport.md to split spoke/hub imports. Resolve binding stability and NAPI/Deno R&D items as covered by the fork path.
69 lines
4.0 KiB
Markdown
69 lines
4.0 KiB
Markdown
---
|
|
status: draft
|
|
last_updated: 2026-05-08
|
|
---
|
|
|
|
# Event Target Adapters
|
|
|
|
All adapters implement the `TypedEventTarget<TEvent>` interface and use the `EventEnvelope` format (`{ type, id, payload }`) as the serialization contract.
|
|
|
|
## Interface Contract
|
|
|
|
Every adapter must implement:
|
|
|
|
| Method | Behavior |
|
|
|--------|----------|
|
|
| `addEventListener(type, callback)` | Register listener for event type. Callback receives `CustomEvent` with typed `detail` (an `EventEnvelope`). |
|
|
| `dispatchEvent(event)` | Send/dispatch event. Returns `boolean` (always `true` for non-cancelable events). |
|
|
| `removeEventListener(type, callback)` | Unregister listener. Clean up underlying subscription when no listeners remain for a topic. |
|
|
|
|
## Topology Model
|
|
|
|
Adapters come in two shapes:
|
|
|
|
- **Symmetric** (single connection) — wraps one connection. Same interface on both sides. Examples: Redis, Iroh spoke, WebSocket client, Worker.
|
|
- **Fan-out** (multi-connection) — manages multiple connections. `dispatchEvent` sends only to connections subscribed to the event type (topic-based fan-out); `addEventListener` aggregates from all. Examples: WebSocket server, Iroh hub.
|
|
|
|
Worker is a symmetric adapter (point-to-point). A Worker pool manager would be a fan-out concern, but that belongs in `@alkdev/operations`, not in this package.
|
|
|
|
The `createPubSub` layer is topology-agnostic. A hub composes multiple adapters and uses operators to combine streams — this is downstream application logic, not a package boundary.
|
|
|
|
## Composing Adapters
|
|
|
|
Adapters compose at the `createPubSub` level, not by nesting adapters. A common pattern:
|
|
|
|
```
|
|
Client (WS spoke) → Server (WS hub) → Redis → Other servers
|
|
```
|
|
|
|
In this topology:
|
|
- The WS hub adapter manages spoke connections with topic-based fan-out
|
|
- The hub's `createPubSub` instance also has a Redis event target for cross-server communication
|
|
- Subscription state at the hub level aggregates: when a spoke subscribes to topic `X`, the hub may also subscribe to `X` on Redis (if no other spoke is already subscribed)
|
|
|
|
This composition is handled by `createPubSub` bridging multiple event targets, not by adapters wrapping each other. The fan-out adapter's subscription tracking is local to its connected spokes; upstream subscriptions are a `createPubSub` concern.
|
|
|
|
## Subscription Control Protocol
|
|
|
|
Fan-out adapters must know which connections are interested in which topics. Symmetric adapters that connect to a fan-out adapter must declare their subscriptions. This is done through **control events** — `EventEnvelope` messages with reserved `__`-prefixed types:
|
|
|
|
- `__subscribe` — sent when a spoke adds the first listener for a topic
|
|
- `__unsubscribe` — sent when a spoke removes the last listener for a topic
|
|
|
|
The `id` field in control events is the empty string (`""`) by convention. Control events use the `topic` field in their payload for routing instead. Control events are handled internally by adapters and never dispatched to user-facing listeners. Event types starting with `__` are reserved — user code must not define event types with this prefix.
|
|
|
|
See [ADR-003](decisions/003-subscription-control-protocol.md).
|
|
|
|
This is analogous to Redis's `SUBSCRIBE`/`UNSUBSCRIBE` commands — control messages share the same wire format and connection as data.
|
|
|
|
## Adapter Docs
|
|
|
|
| Adapter | Import | Status |
|
|
|---------|--------|--------|
|
|
| [In-Process](in-process.md) | (default, no import) | Implemented (built-in `EventTarget`) |
|
|
| [Redis](redis.md) | `@alkdev/pubsub/event-target-redis` | Implemented. Needs tests. |
|
|
| [WebSocket Client](websocket-client.md) | `@alkdev/pubsub/event-target-websocket-client` | Not yet implemented |
|
|
| [WebSocket Server](websocket-server.md) | `@alkdev/pubsub/event-target-websocket-server` | Not yet implemented |
|
|
| [Worker](worker.md) | `@alkdev/pubsub/event-target-worker` | Not yet implemented (R&D on Node vs Web Worker) |
|
|
| [Iroh Spoke](iroh-spoke.md) | `@alkdev/pubsub/event-target-iroh-spoke` | Deferred (pending fork of iroh-ts) |
|
|
| [Iroh Hub](iroh-hub.md) | `@alkdev/pubsub/event-target-iroh-hub` | Deferred (pending fork of iroh-ts) | |