Files
pubsub/docs/architecture/event-targets/redis.md
glm-5.1 371dabc20d Add per-adapter architecture docs in event-targets/ directory
- Create docs/architecture/event-targets/ with individual specs:
  in-process, redis, websocket-client, websocket-server,
  worker, iroh-spoke, iroh-hub
- Update event-targets.md to serve as index with topology model
  (symmetric vs fan-out) and adapter status table
- Update architecture.md index to reference new directory
2026-05-07 14:49:50 +00:00

59 lines
2.6 KiB
Markdown

---
status: draft
last_updated: 2026-05-07
---
# Redis Event Target
**Import**: `@alkdev/pubsub/event-target-redis`
**Peer dep**: `ioredis@^5.0.0` (optional)
**Status**: Implemented. Needs tests.
Adapted from `@graphql-yoga/redis-event-target` (MIT).
## `createRedisEventTarget`
```ts
function createRedisEventTarget<TEvent extends TypedEvent>(
args: CreateRedisEventTargetArgs,
): TypedEventTarget<TEvent>;
```
### `CreateRedisEventTargetArgs`
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `publishClient` | `Redis \| Cluster` | Yes | ioredis client for publishing. Can share a connection. |
| `subscribeClient` | `Redis \| Cluster` | Yes | ioredis client for subscribing. Must be dedicated — Redis requires subscriber connections to only receive messages. |
| `serializer` | `{ stringify, parse }` | No | Custom serializer. Defaults to `JSON`. |
## How It Works
- `dispatchEvent``publishClient.publish(event.type, serializer.stringify(event.detail))`
- `addEventListener``subscribeClient.subscribe(topic)`, track callbacks per topic
- `removeEventListener` → remove callback; if no callbacks remain for topic, `subscribeClient.unsubscribe(topic)`
- On message: deserializes with `serializer.parse`, reconstructs `CustomEvent(channel, { detail: envelope })`
The `detail` of the `CustomEvent` dispatched to local listeners is the full `EventEnvelope` object (`{ type, id, payload }`).
## Channel Naming
Currently uses the topic string directly as the Redis channel name (e.g., `call.responded:uuid-123`). Should support a configurable prefix: `createRedisEventTarget({ ..., prefix: "alk:events:" })`.
## Limitations (Current)
- **No error handling** — connection failures, reconnection, and message parse errors are not handled
- **No channel prefix** — raw event types as channel names risk collision in shared Redis instances
- **No unsubscribe cleanup on client disconnect** — if the subscribe client disconnects, registered callbacks remain in the map but will never fire
## Test Coverage
No tests yet. Need:
1. **Publish path** — dispatchEvent sends to Redis with correct channel and serialized envelope
2. **Subscribe path** — addEventListener subscribes to Redis, onMessage dispatches to local listeners
3. **Unsubscribe** — removeEventListener unsubscribes from Redis when no listeners remain for a topic
4. **Topic scoping** — type:id topics are correctly formed
5. **Envelope serialization** — full `{ type, id, payload }` round-trips through JSON
6. **Multiple listeners** — multiple listeners on same topic, single Redis subscribe
7. **Error propagation** — what happens on connection failure