@beignet/provider-event-bus-redis 0.0.48 → 0.0.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +47 -10
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +271 -147
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +358 -192
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @beignet/provider-event-bus-redis
|
|
2
2
|
|
|
3
|
+
## 0.0.50
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6fe026a: Expose event-subscription readiness and asynchronous cleanup, await listener
|
|
8
|
+
registries during provider startup with bounded rollback, diagnose unsafe app
|
|
9
|
+
wiring, and make Redis subscription lifecycle failures observable with bounded
|
|
10
|
+
provider shutdown and recoverable channel state.
|
|
11
|
+
|
|
12
|
+
## 0.0.49
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- e597d53: Require Node.js 22.12 or newer across every Beignet package, generated app,
|
|
17
|
+
and documented workflow.
|
|
18
|
+
|
|
3
19
|
## 0.0.48
|
|
4
20
|
|
|
5
21
|
## 0.0.47
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @beignet/provider-event-bus-redis
|
|
2
2
|
|
|
3
|
+
> **Runtime:** Beignet requires Node.js 22.12 or newer. Bun 1.3.14 or newer is
|
|
4
|
+
> supported for Beignet commands.
|
|
5
|
+
|
|
3
6
|
> [!CAUTION]
|
|
4
7
|
> Beignet is experimental alpha software. The `0.0.x` package line is for early
|
|
5
8
|
> evaluation, and APIs may change between releases while the framework settles.
|
|
@@ -65,6 +68,7 @@ The provider reads environment variables with the `REDIS_EVENT_BUS_` prefix:
|
|
|
65
68
|
| `REDIS_EVENT_BUS_DB` | No | Redis database number. Defaults to `0`. | `0` |
|
|
66
69
|
| `REDIS_EVENT_BUS_CHANNEL_PREFIX` | No | Prefix for Pub/Sub channels. Defaults to `beignet:event-bus:`. | `my-app:events:` |
|
|
67
70
|
| `REDIS_EVENT_BUS_CONNECT_TIMEOUT_MS` | No | Initial connection timeout in milliseconds. Defaults to `5000`. | `2000` |
|
|
71
|
+
| `REDIS_EVENT_BUS_CLEANUP_TIMEOUT_MS` | No | Shutdown deadline for subscription cleanup in milliseconds. Defaults to `10000`. | `5000` |
|
|
68
72
|
| `REDIS_EVENT_BUS_MAX_RETRIES_PER_REQUEST` | No | Per-command retry limit before a command rejects. Defaults to `2`. | `1` |
|
|
69
73
|
| `REDIS_EVENT_BUS_CONNECT_MAX_ATTEMPTS` | No | Connection attempts before startup fails. Defaults to `3`. | `5` |
|
|
70
74
|
|
|
@@ -80,6 +84,7 @@ import { createRedisEventBusProvider } from "@beignet/provider-event-bus-redis";
|
|
|
80
84
|
const provider = createRedisEventBusProvider({
|
|
81
85
|
channelPrefix: "my-app:events:",
|
|
82
86
|
connectTimeoutMs: 2000,
|
|
87
|
+
cleanupTimeoutMs: 5000,
|
|
83
88
|
maxRetriesPerRequest: 1,
|
|
84
89
|
db: 1,
|
|
85
90
|
retryStrategy: (times) => Math.min(times * 100, 1000),
|
|
@@ -128,7 +133,17 @@ Use `createRedisEventBus(...)` when your app owns Redis clients:
|
|
|
128
133
|
|
|
129
134
|
```typescript
|
|
130
135
|
import Redis from "ioredis";
|
|
136
|
+
import { defineEvent } from "@beignet/core/events";
|
|
131
137
|
import { createRedisEventBus } from "@beignet/provider-event-bus-redis";
|
|
138
|
+
import { z } from "zod";
|
|
139
|
+
|
|
140
|
+
const UserRegistered = defineEvent("user.registered", {
|
|
141
|
+
payload: z.object({ userId: z.string() }),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function handleUserRegistered(payload: { userId: string }) {
|
|
145
|
+
console.log(`Registered ${payload.userId}`);
|
|
146
|
+
}
|
|
132
147
|
|
|
133
148
|
const publisher = new Redis(process.env.REDIS_EVENT_BUS_URL);
|
|
134
149
|
const subscriber = new Redis(process.env.REDIS_EVENT_BUS_URL);
|
|
@@ -138,25 +153,47 @@ const eventBus = createRedisEventBus({
|
|
|
138
153
|
channelPrefix: "my-app:events:",
|
|
139
154
|
});
|
|
140
155
|
|
|
156
|
+
const subscription = eventBus.subscribe(UserRegistered, handleUserRegistered);
|
|
157
|
+
await subscription.ready;
|
|
158
|
+
|
|
141
159
|
// During app shutdown:
|
|
142
|
-
|
|
143
|
-
await
|
|
160
|
+
try {
|
|
161
|
+
await eventBus.stop();
|
|
162
|
+
await Promise.all([publisher.quit(), subscriber.quit()]);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
subscriber.disconnect();
|
|
165
|
+
publisher.disconnect();
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
144
168
|
```
|
|
145
169
|
|
|
146
|
-
Register listeners during startup before handling traffic
|
|
147
|
-
subscription
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
Register listeners during startup before handling traffic and await each
|
|
171
|
+
subscription's `ready` promise. It resolves after Redis acknowledges the
|
|
172
|
+
channel subscription. Failed subscription commands retry with capped backoff
|
|
173
|
+
while a local handler remains; callers can own a deadline, and
|
|
174
|
+
`registerListeners(...)` applies one 10-second deadline to a complete registry
|
|
175
|
+
by default. Readiness proves initial registration only and does not change
|
|
176
|
+
Pub/Sub's online-only delivery semantics.
|
|
177
|
+
|
|
178
|
+
Await `unsubscribe()` when removing an individual handler. During adapter
|
|
179
|
+
shutdown, `stop()` closes all remaining subscriptions, detaches local delivery,
|
|
180
|
+
cancels pending retries, and awaits channel cleanup. Cleanup errors reject and
|
|
181
|
+
are instrumented; `stop()` retries channels left dirty by an earlier
|
|
182
|
+
unsubscribe before reporting any remaining failure. To keep lifecycle rollback
|
|
183
|
+
bounded, `stop()` rejects after `cleanupTimeoutMs` (10 seconds by default) even
|
|
184
|
+
if an ioredis command never settles. The adapter does not close caller-owned
|
|
185
|
+
Redis clients, so force-disconnect them when cleanup rejects. Stopping is
|
|
186
|
+
terminal: later subscription attempts reject instead of creating handlers that
|
|
187
|
+
cannot receive messages.
|
|
154
188
|
|
|
155
189
|
## Delivery semantics
|
|
156
190
|
|
|
157
191
|
- `publish(...)` publishes one Redis Pub/Sub message on
|
|
158
192
|
`<channelPrefix><event.name>`.
|
|
159
193
|
- Only subscribers that are online and currently subscribed receive the event.
|
|
194
|
+
- A subscription's `ready` promise resolves only after the initial Redis
|
|
195
|
+
subscription acknowledgement. Cancelling before acknowledgement rejects that
|
|
196
|
+
promise and prevents future local delivery.
|
|
160
197
|
- ioredis resubscribes after a transient reconnect, but messages published
|
|
161
198
|
during the disconnected interval are not recovered.
|
|
162
199
|
- Payloads are JSON encoded and delivered to handlers without persisting the
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface RedisEventBusConfig {
|
|
|
14
14
|
DB?: number;
|
|
15
15
|
CHANNEL_PREFIX: string;
|
|
16
16
|
CONNECT_TIMEOUT_MS: number;
|
|
17
|
+
CLEANUP_TIMEOUT_MS: number;
|
|
17
18
|
MAX_RETRIES_PER_REQUEST: number;
|
|
18
19
|
CONNECT_MAX_ATTEMPTS: number;
|
|
19
20
|
}
|
|
@@ -57,6 +58,8 @@ export interface CreateRedisEventBusOptions {
|
|
|
57
58
|
publisher: RedisEventBusPublisherClient;
|
|
58
59
|
subscriber: RedisEventBusSubscriberClient;
|
|
59
60
|
channelPrefix?: string;
|
|
61
|
+
/** Maximum time to await subscription cleanup before `stop()` rejects. */
|
|
62
|
+
cleanupTimeoutMs?: number;
|
|
60
63
|
instrumentation?: ProviderInstrumentationTarget;
|
|
61
64
|
onHandlerError?: (error: unknown, eventName: string, payload: unknown) => void;
|
|
62
65
|
onSubscriberError?: (error: unknown) => void;
|
|
@@ -64,6 +67,8 @@ export interface CreateRedisEventBusOptions {
|
|
|
64
67
|
export interface CreateRedisEventBusProviderOptions {
|
|
65
68
|
channelPrefix?: string;
|
|
66
69
|
connectTimeoutMs?: number;
|
|
70
|
+
/** Maximum time to await subscription cleanup before forcing disconnect. */
|
|
71
|
+
cleanupTimeoutMs?: number;
|
|
67
72
|
maxRetriesPerRequest?: number;
|
|
68
73
|
retryStrategy?: (times: number) => number | null;
|
|
69
74
|
db?: number;
|
|
@@ -77,8 +82,8 @@ export interface CreateRedisEventBusProviderOptions {
|
|
|
77
82
|
*/
|
|
78
83
|
export interface RedisEventBus extends EventBusPort {
|
|
79
84
|
/**
|
|
80
|
-
* Stop local delivery and
|
|
81
|
-
*
|
|
85
|
+
* Stop local delivery and await cleanup of the adapter's channels without
|
|
86
|
+
* closing the caller-owned Redis clients.
|
|
82
87
|
*/
|
|
83
88
|
stop(): Promise<void>;
|
|
84
89
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,uBAAuB,EAG5B,KAAK,6BAA6B,EAClC,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AA2CjC;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACpE,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,WAAW,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC/D,EAAE,CACA,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAC;IACX,GAAG,CAAC,CACF,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAC;IACX,cAAc,CAAC,CACb,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAC;IACX,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QACR,OAAO,EAAE,iBAAiB,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,4BAA4B,CAAC;IACxC,UAAU,EAAE,6BAA6B,CAAC;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,YAAY,CAAC;IACvB,aAAa,EAAE,wBAAwB,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,eAAe,CACjD,OAAO,EACP,uBAAuB,CAAC,mBAAmB,CAAC,EAC5C,IAAI,CAAC,0BAA0B,EAAE,MAAM,0BAA0B,CAAC,CACnE,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,4BAA4B,CAAC;IACxC,UAAU,EAAE,6BAA6B,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,KACb,IAAI,CAAC;IACV,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,kCAAkC;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAuID;;;;;;GAMG;AACH,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AA8eD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,aAAa,CAEf;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kCAAuC,GAC/C,qBAAqB,CAyLvB"}
|