@beignet/provider-event-bus-redis 0.0.37 → 0.0.39
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 +17 -0
- package/README.md +58 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +197 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +268 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @beignet/provider-event-bus-redis
|
|
2
2
|
|
|
3
|
+
## 0.0.39
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 019db95: Report Redis publish, connection, and subscription failures consistently,
|
|
8
|
+
retry desired subscriptions after transient command failures, preserve visible
|
|
9
|
+
connection-error fallback logging, isolate rejected error callbacks, and
|
|
10
|
+
document the provider's proven reconnect and deployment semantics.
|
|
11
|
+
|
|
12
|
+
## 0.0.38
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 1081ac6: Harden HTTP response handling, synchronous upload cleanup, CLI path and registry diagnostics, provider context preservation, Redis subscription observability, and provider documentation.
|
|
17
|
+
- d23b0b3: Continue versioned W3C trace context through outbox, event bus, BullMQ, and
|
|
18
|
+
Inngest boundaries without making telemetry metadata part of delivery success.
|
|
19
|
+
|
|
3
20
|
## 0.0.37
|
|
4
21
|
|
|
5
22
|
## 0.0.36
|
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ beignet providers add event-bus-redis
|
|
|
34
34
|
```typescript
|
|
35
35
|
import { createNextServer, createNextServerLoader } from "@beignet/next";
|
|
36
36
|
import { createRedisEventBusProvider } from "@beignet/provider-event-bus-redis";
|
|
37
|
-
import {
|
|
37
|
+
import { initialPorts } from "@/infra/port-wiring";
|
|
38
38
|
import { routes } from "@/server/routes";
|
|
39
39
|
|
|
40
40
|
// Set environment variables:
|
|
@@ -43,7 +43,7 @@ import { routes } from "@/server/routes";
|
|
|
43
43
|
|
|
44
44
|
export const getServer = createNextServerLoader(() =>
|
|
45
45
|
createNextServer({
|
|
46
|
-
ports:
|
|
46
|
+
ports: initialPorts,
|
|
47
47
|
providers: [createRedisEventBusProvider()],
|
|
48
48
|
context: ({ ports }) => ({
|
|
49
49
|
ports,
|
|
@@ -96,7 +96,32 @@ During startup the provider creates separate publisher and subscriber clients,
|
|
|
96
96
|
connects both eagerly, and fails boot with a redacted connection error when
|
|
97
97
|
Redis is unreachable. The default initial connection retry strategy stops
|
|
98
98
|
after `REDIS_EVENT_BUS_CONNECT_MAX_ATTEMPTS`; after a successful connection,
|
|
99
|
-
ioredis reconnects with capped exponential backoff
|
|
99
|
+
ioredis reconnects with capped exponential backoff and resubscribes to the
|
|
100
|
+
channels owned by that subscriber client. Events published while the
|
|
101
|
+
subscriber is disconnected are still lost because Redis Pub/Sub has no replay.
|
|
102
|
+
If an initial `SUBSCRIBE` command fails after ioredis exhausts its command
|
|
103
|
+
retries, the adapter retries that desired subscription with capped backoff for
|
|
104
|
+
as long as at least one local handler remains registered.
|
|
105
|
+
|
|
106
|
+
### Deployment topology
|
|
107
|
+
|
|
108
|
+
The environment-backed provider targets a standalone Redis URL or a managed
|
|
109
|
+
Redis service that exposes one Redis-compatible endpoint. It opens two TCP
|
|
110
|
+
connections per app process: one publisher and one subscriber. Include both in
|
|
111
|
+
the process connection budget.
|
|
112
|
+
|
|
113
|
+
Every long-lived process that should receive events must install the provider
|
|
114
|
+
and register its listeners. Ephemeral request runtimes can publish events, but
|
|
115
|
+
they are not reliable subscriber hosts because Redis only delivers while the
|
|
116
|
+
connection is online. Run subscriptions in a long-lived web or worker process.
|
|
117
|
+
|
|
118
|
+
Sentinel and Redis Cluster require constructor options that cannot be expressed
|
|
119
|
+
by `REDIS_EVENT_BUS_URL`. Apps using those topologies should create their own
|
|
120
|
+
ioredis clients and pass them to `createRedisEventBus(...)`. Beignet's live
|
|
121
|
+
suite does not currently prove Sentinel or Cluster failover semantics, so test
|
|
122
|
+
subscription recovery against the exact managed topology before relying on it.
|
|
123
|
+
HTTP-only Redis APIs are not compatible because Pub/Sub requires a persistent
|
|
124
|
+
Redis connection.
|
|
100
125
|
|
|
101
126
|
## Direct adapter
|
|
102
127
|
|
|
@@ -123,13 +148,31 @@ missed during startup races.
|
|
|
123
148
|
- `publish(...)` publishes one Redis Pub/Sub message on
|
|
124
149
|
`<channelPrefix><event.name>`.
|
|
125
150
|
- Only subscribers that are online and currently subscribed receive the event.
|
|
151
|
+
- ioredis resubscribes after a transient reconnect, but messages published
|
|
152
|
+
during the disconnected interval are not recovered.
|
|
126
153
|
- Payloads are JSON encoded and delivered to handlers without persisting the
|
|
127
154
|
message.
|
|
155
|
+
- When a tracing port is available, the envelope includes Beignet's versioned
|
|
156
|
+
trace carrier and subscribers receive it as publish metadata. Registered
|
|
157
|
+
listeners continue the producer trace. Legacy messages without a carrier and
|
|
158
|
+
messages with malformed trace metadata still deliver their payload.
|
|
128
159
|
- Handler errors are reported through `onHandlerError` when provided and are
|
|
129
160
|
also recorded as provider instrumentation events; they do not reject the
|
|
130
161
|
original publisher.
|
|
131
162
|
- Invalid messages and subscription errors are reported through
|
|
132
|
-
`onSubscriberError` when provided
|
|
163
|
+
`onSubscriberError` when provided and recorded as
|
|
164
|
+
`eventBus.message.failed` or `eventBus.subscription.failed` provider
|
|
165
|
+
instrumentation events. Failed subscriptions retry with capped backoff while
|
|
166
|
+
their local handlers remain registered; removing the last handler cancels a
|
|
167
|
+
pending retry.
|
|
168
|
+
- Failed `publish(...)` calls reject with the Redis error and record an
|
|
169
|
+
`eventBus.publish.failed` instrumentation event. The provider does not retry
|
|
170
|
+
the publish after the configured ioredis command retries are exhausted.
|
|
171
|
+
- When the `eventBus` instrumentation watcher is enabled, publisher and
|
|
172
|
+
subscriber connection errors from env-backed clients are recorded as
|
|
173
|
+
`eventBus.connection.failed`. When instrumentation is absent or disabled,
|
|
174
|
+
Beignet leaves ioredis's error fallback intact so connection failures remain
|
|
175
|
+
visible.
|
|
133
176
|
- The provider does not retry handlers, store attempts, replay missed events,
|
|
134
177
|
or dead-letter failures.
|
|
135
178
|
|
|
@@ -150,12 +193,15 @@ ctx.ports.redisEventBus.channelPrefix;
|
|
|
150
193
|
```
|
|
151
194
|
|
|
152
195
|
`checkHealth()` sends cheap `PING` commands to both Redis clients and returns
|
|
153
|
-
metadata suitable for app-owned readiness endpoints.
|
|
196
|
+
metadata suitable for app-owned readiness endpoints. It proves both
|
|
197
|
+
connections can reach Redis; it does not prove that every expected listener
|
|
198
|
+
has registered its channel subscription.
|
|
154
199
|
|
|
155
200
|
## Instrumentation
|
|
156
201
|
|
|
157
|
-
The provider records publish events under the `eventBus` watcher.
|
|
158
|
-
messages
|
|
202
|
+
The provider records successful publish events under the `eventBus` watcher.
|
|
203
|
+
Received messages, failed publishes, connection failures, subscription
|
|
204
|
+
failures, and handler failures are recorded as custom provider events. Payloads
|
|
159
205
|
are not recorded.
|
|
160
206
|
|
|
161
207
|
## Testing
|
|
@@ -166,9 +212,11 @@ the behavior under test specifically depends on cross-process delivery or
|
|
|
166
212
|
Redis connection behavior.
|
|
167
213
|
|
|
168
214
|
This package includes opt-in live Redis integration tests for cross-instance
|
|
169
|
-
delivery,
|
|
170
|
-
|
|
171
|
-
|
|
215
|
+
delivery, reconnect and automatic resubscription, expected loss while offline,
|
|
216
|
+
active-subscription cleanup during shutdown, readiness, instrumentation, and
|
|
217
|
+
failure callbacks. The default `bun run test` command runs the hermetic unit
|
|
218
|
+
suite only so the live tests cannot share process state with the mocked
|
|
219
|
+
`ioredis` tests.
|
|
172
220
|
Set `REDIS_EVENT_BUS_TEST_URL` or the shared `REDIS_TEST_URL` before running
|
|
173
221
|
the dedicated live test command:
|
|
174
222
|
|
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;AAEH,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,uBAAuB,EAG5B,KAAK,6BAA6B,EAClC,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* cross-process, best-effort domain event delivery.
|
|
6
6
|
*/
|
|
7
7
|
import { createProvider, createProviderInstrumentation, } from "@beignet/core/providers";
|
|
8
|
+
import { captureTraceCarrier, parseTraceCarrier, } from "@beignet/core/tracing";
|
|
8
9
|
import { Redis } from "ioredis";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
const DEFAULT_CONNECT_TIMEOUT_MS = 5000;
|
|
@@ -12,6 +13,8 @@ const DEFAULT_MAX_RETRIES_PER_REQUEST = 2;
|
|
|
12
13
|
const DEFAULT_CONNECT_MAX_ATTEMPTS = 3;
|
|
13
14
|
const DEFAULT_CHANNEL_PREFIX = "beignet:event-bus:";
|
|
14
15
|
const RECONNECT_BACKOFF_CAP_MS = 2000;
|
|
16
|
+
const SUBSCRIPTION_RETRY_BASE_MS = 100;
|
|
17
|
+
const SUBSCRIPTION_RETRY_CAP_MS = 2000;
|
|
15
18
|
const NumberString = z.union([
|
|
16
19
|
z
|
|
17
20
|
.string()
|
|
@@ -49,6 +52,9 @@ function redactConnectionUrl(url) {
|
|
|
49
52
|
function reconnectBackoff(attempt) {
|
|
50
53
|
return Math.min(2 ** attempt * 100, RECONNECT_BACKOFF_CAP_MS);
|
|
51
54
|
}
|
|
55
|
+
function subscriptionRetryBackoff(attempt) {
|
|
56
|
+
return Math.min(SUBSCRIPTION_RETRY_BASE_MS * 2 ** Math.max(0, attempt - 1), SUBSCRIPTION_RETRY_CAP_MS);
|
|
57
|
+
}
|
|
52
58
|
function createRetryStrategy(connectMaxAttempts) {
|
|
53
59
|
let connectedOnce = false;
|
|
54
60
|
return {
|
|
@@ -105,20 +111,36 @@ async function checkRedisEventBusHealth(publisher, subscriber, channelPrefix) {
|
|
|
105
111
|
};
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
|
-
|
|
114
|
+
function createRedisEventBusRuntime(options) {
|
|
109
115
|
const channelPrefix = options.channelPrefix ?? DEFAULT_CHANNEL_PREFIX;
|
|
110
116
|
const handlers = new Map();
|
|
111
|
-
const subscribedChannels = new
|
|
117
|
+
const subscribedChannels = new Map();
|
|
118
|
+
const subscriptionRetryAttempts = new Map();
|
|
119
|
+
const subscriptionRetryTimers = new Map();
|
|
120
|
+
let stopped = false;
|
|
112
121
|
const instrumentation = createProviderInstrumentation(options.instrumentation, {
|
|
113
122
|
providerName: "event-bus-redis",
|
|
114
123
|
watcher: "eventBus",
|
|
115
124
|
});
|
|
116
|
-
const reportSubscriberError = (error) => {
|
|
125
|
+
const reportSubscriberError = (error, details) => {
|
|
126
|
+
instrumentation.custom({
|
|
127
|
+
name: details.operation === "message"
|
|
128
|
+
? "eventBus.message.failed"
|
|
129
|
+
: "eventBus.subscription.failed",
|
|
130
|
+
label: details.operation === "message"
|
|
131
|
+
? "Event message failed"
|
|
132
|
+
: "Event subscription failed",
|
|
133
|
+
summary: details.eventName ?? details.channel ?? "Redis event bus subscriber",
|
|
134
|
+
details: {
|
|
135
|
+
...details,
|
|
136
|
+
error: errorMessage(error),
|
|
137
|
+
},
|
|
138
|
+
});
|
|
117
139
|
try {
|
|
118
|
-
options.onSubscriberError?.(error);
|
|
140
|
+
Promise.resolve(options.onSubscriberError?.(error)).catch(() => undefined);
|
|
119
141
|
}
|
|
120
142
|
catch {
|
|
121
|
-
// Error callbacks should not create
|
|
143
|
+
// Error callbacks should not replace or create another failure.
|
|
122
144
|
}
|
|
123
145
|
};
|
|
124
146
|
const reportHandlerError = (error, eventName, payload) => {
|
|
@@ -132,10 +154,10 @@ export function createRedisEventBus(options) {
|
|
|
132
154
|
},
|
|
133
155
|
});
|
|
134
156
|
try {
|
|
135
|
-
options.onHandlerError?.(error, eventName, payload);
|
|
157
|
+
Promise.resolve(options.onHandlerError?.(error, eventName, payload)).catch(() => undefined);
|
|
136
158
|
}
|
|
137
159
|
catch {
|
|
138
|
-
// Error callbacks should not create
|
|
160
|
+
// Error callbacks should not replace or create another failure.
|
|
139
161
|
}
|
|
140
162
|
};
|
|
141
163
|
const messageHandler = (channel, message) => {
|
|
@@ -146,6 +168,7 @@ export function createRedisEventBus(options) {
|
|
|
146
168
|
if (!eventHandlers || eventHandlers.size === 0)
|
|
147
169
|
return;
|
|
148
170
|
let payload;
|
|
171
|
+
let trace;
|
|
149
172
|
try {
|
|
150
173
|
const parsed = safeJsonParse(message);
|
|
151
174
|
if (typeof parsed !== "object" ||
|
|
@@ -153,10 +176,16 @@ export function createRedisEventBus(options) {
|
|
|
153
176
|
!("payload" in parsed)) {
|
|
154
177
|
throw new Error("Redis event bus message is missing a payload field.");
|
|
155
178
|
}
|
|
156
|
-
|
|
179
|
+
const envelope = parsed;
|
|
180
|
+
payload = envelope.payload;
|
|
181
|
+
trace = parseTraceCarrier(envelope.trace);
|
|
157
182
|
}
|
|
158
183
|
catch (error) {
|
|
159
|
-
reportSubscriberError(error
|
|
184
|
+
reportSubscriberError(error, {
|
|
185
|
+
operation: "message",
|
|
186
|
+
channel,
|
|
187
|
+
eventName,
|
|
188
|
+
});
|
|
160
189
|
return;
|
|
161
190
|
}
|
|
162
191
|
instrumentation.custom({
|
|
@@ -167,7 +196,7 @@ export function createRedisEventBus(options) {
|
|
|
167
196
|
});
|
|
168
197
|
for (const handler of [...eventHandlers]) {
|
|
169
198
|
try {
|
|
170
|
-
Promise.resolve(handler(payload)).catch((error) => {
|
|
199
|
+
Promise.resolve(handler(payload, trace ? { trace } : undefined)).catch((error) => {
|
|
171
200
|
reportHandlerError(error, eventName, payload);
|
|
172
201
|
});
|
|
173
202
|
}
|
|
@@ -177,29 +206,106 @@ export function createRedisEventBus(options) {
|
|
|
177
206
|
}
|
|
178
207
|
};
|
|
179
208
|
options.subscriber.on("message", messageHandler);
|
|
209
|
+
const scheduleSubscriptionRetry = (eventName) => {
|
|
210
|
+
const channel = channelForEvent(channelPrefix, eventName);
|
|
211
|
+
if (stopped ||
|
|
212
|
+
subscriptionRetryTimers.has(channel) ||
|
|
213
|
+
!handlers.get(eventName)?.size) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const retryAttempt = (subscriptionRetryAttempts.get(channel) ?? 0) + 1;
|
|
217
|
+
subscriptionRetryAttempts.set(channel, retryAttempt);
|
|
218
|
+
const timer = setTimeout(() => {
|
|
219
|
+
subscriptionRetryTimers.delete(channel);
|
|
220
|
+
ensureSubscribed(eventName);
|
|
221
|
+
}, subscriptionRetryBackoff(retryAttempt));
|
|
222
|
+
timer.unref?.();
|
|
223
|
+
subscriptionRetryTimers.set(channel, timer);
|
|
224
|
+
};
|
|
180
225
|
const ensureSubscribed = (eventName) => {
|
|
181
226
|
const channel = channelForEvent(channelPrefix, eventName);
|
|
182
|
-
if (
|
|
227
|
+
if (stopped ||
|
|
228
|
+
subscribedChannels.has(channel) ||
|
|
229
|
+
subscriptionRetryTimers.has(channel)) {
|
|
183
230
|
return;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
231
|
+
}
|
|
232
|
+
const attempt = Symbol(channel);
|
|
233
|
+
subscribedChannels.set(channel, attempt);
|
|
234
|
+
const onFailure = (error) => {
|
|
235
|
+
if (subscribedChannels.get(channel) === attempt) {
|
|
236
|
+
subscribedChannels.delete(channel);
|
|
237
|
+
scheduleSubscriptionRetry(eventName);
|
|
238
|
+
}
|
|
239
|
+
reportSubscriberError(error, {
|
|
240
|
+
operation: "subscribe",
|
|
241
|
+
channel,
|
|
242
|
+
eventName,
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
try {
|
|
246
|
+
Promise.resolve(options.subscriber.subscribe(channel)).then(() => {
|
|
247
|
+
if (subscribedChannels.get(channel) === attempt) {
|
|
248
|
+
subscriptionRetryAttempts.delete(channel);
|
|
249
|
+
}
|
|
250
|
+
}, onFailure);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
onFailure(error);
|
|
254
|
+
}
|
|
189
255
|
};
|
|
190
256
|
const unsubscribeChannel = (eventName) => {
|
|
191
257
|
const channel = channelForEvent(channelPrefix, eventName);
|
|
192
|
-
|
|
258
|
+
const retryTimer = subscriptionRetryTimers.get(channel);
|
|
259
|
+
if (retryTimer) {
|
|
260
|
+
clearTimeout(retryTimer);
|
|
261
|
+
subscriptionRetryTimers.delete(channel);
|
|
262
|
+
}
|
|
263
|
+
subscriptionRetryAttempts.delete(channel);
|
|
264
|
+
if (!subscribedChannels.has(channel))
|
|
193
265
|
return;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
eventName: event.name,
|
|
266
|
+
subscribedChannels.delete(channel);
|
|
267
|
+
const onFailure = (error) => {
|
|
268
|
+
reportSubscriberError(error, {
|
|
269
|
+
operation: "unsubscribe",
|
|
270
|
+
channel,
|
|
271
|
+
eventName,
|
|
201
272
|
});
|
|
202
|
-
|
|
273
|
+
};
|
|
274
|
+
try {
|
|
275
|
+
Promise.resolve(options.subscriber.unsubscribe(channel)).catch(onFailure);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
onFailure(error);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
const eventBus = {
|
|
282
|
+
async publish(event, payload, publishOptions) {
|
|
283
|
+
const trace = parseTraceCarrier(publishOptions?.trace) ??
|
|
284
|
+
captureTraceCarrier(options.instrumentation);
|
|
285
|
+
try {
|
|
286
|
+
await options.publisher.publish(channelForEvent(channelPrefix, event.name), JSON.stringify({
|
|
287
|
+
eventName: event.name,
|
|
288
|
+
payload,
|
|
289
|
+
...(trace ? { trace } : {}),
|
|
290
|
+
}));
|
|
291
|
+
instrumentation.record({
|
|
292
|
+
type: "eventBus",
|
|
293
|
+
eventName: event.name,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
instrumentation.custom({
|
|
298
|
+
name: "eventBus.publish.failed",
|
|
299
|
+
label: "Event publish failed",
|
|
300
|
+
summary: `Publish failed for "${event.name}"`,
|
|
301
|
+
details: {
|
|
302
|
+
operation: "publish",
|
|
303
|
+
eventName: event.name,
|
|
304
|
+
error: errorMessage(error),
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
203
309
|
},
|
|
204
310
|
subscribe(event, handler) {
|
|
205
311
|
let eventHandlers = handlers.get(event.name);
|
|
@@ -221,6 +327,28 @@ export function createRedisEventBus(options) {
|
|
|
221
327
|
};
|
|
222
328
|
},
|
|
223
329
|
};
|
|
330
|
+
return {
|
|
331
|
+
eventBus,
|
|
332
|
+
stop() {
|
|
333
|
+
stopped = true;
|
|
334
|
+
for (const timer of subscriptionRetryTimers.values()) {
|
|
335
|
+
clearTimeout(timer);
|
|
336
|
+
}
|
|
337
|
+
subscriptionRetryTimers.clear();
|
|
338
|
+
subscriptionRetryAttempts.clear();
|
|
339
|
+
subscribedChannels.clear();
|
|
340
|
+
handlers.clear();
|
|
341
|
+
if (options.subscriber.off) {
|
|
342
|
+
options.subscriber.off("message", messageHandler);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
options.subscriber.removeListener?.("message", messageHandler);
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
export function createRedisEventBus(options) {
|
|
351
|
+
return createRedisEventBusRuntime(options).eventBus;
|
|
224
352
|
}
|
|
225
353
|
export function createRedisEventBusProvider(options = {}) {
|
|
226
354
|
const providerMetadata = {
|
|
@@ -279,6 +407,39 @@ export function createRedisEventBusProvider(options = {}) {
|
|
|
279
407
|
...redisOptions,
|
|
280
408
|
retryStrategy: options.retryStrategy ?? subscriberRetry.strategy,
|
|
281
409
|
});
|
|
410
|
+
const connectionInstrumentation = createProviderInstrumentation(ports, {
|
|
411
|
+
providerName: "event-bus-redis",
|
|
412
|
+
watcher: "eventBus",
|
|
413
|
+
});
|
|
414
|
+
const reportPublisherConnectionError = (error) => {
|
|
415
|
+
connectionInstrumentation.custom({
|
|
416
|
+
name: "eventBus.connection.failed",
|
|
417
|
+
label: "Event bus connection failed",
|
|
418
|
+
summary: "Redis event bus publisher connection failed",
|
|
419
|
+
details: {
|
|
420
|
+
operation: "connection",
|
|
421
|
+
role: "publisher",
|
|
422
|
+
error: errorMessage(error),
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
};
|
|
426
|
+
const reportSubscriberConnectionError = (error) => {
|
|
427
|
+
connectionInstrumentation.custom({
|
|
428
|
+
name: "eventBus.connection.failed",
|
|
429
|
+
label: "Event bus connection failed",
|
|
430
|
+
summary: "Redis event bus subscriber connection failed",
|
|
431
|
+
details: {
|
|
432
|
+
operation: "connection",
|
|
433
|
+
role: "subscriber",
|
|
434
|
+
error: errorMessage(error),
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
const observeConnectionErrors = connectionInstrumentation.isEnabled();
|
|
439
|
+
if (observeConnectionErrors) {
|
|
440
|
+
publisher.on("error", reportPublisherConnectionError);
|
|
441
|
+
subscriber.on("error", reportSubscriberConnectionError);
|
|
442
|
+
}
|
|
282
443
|
try {
|
|
283
444
|
await publisher.connect();
|
|
284
445
|
publisherRetry.markConnected();
|
|
@@ -286,16 +447,21 @@ export function createRedisEventBusProvider(options = {}) {
|
|
|
286
447
|
subscriberRetry.markConnected();
|
|
287
448
|
}
|
|
288
449
|
catch (error) {
|
|
450
|
+
if (observeConnectionErrors) {
|
|
451
|
+
publisher.off("error", reportPublisherConnectionError);
|
|
452
|
+
subscriber.off("error", reportSubscriberConnectionError);
|
|
453
|
+
}
|
|
289
454
|
publisher.disconnect();
|
|
290
455
|
subscriber.disconnect();
|
|
291
456
|
throw new Error(`[createRedisEventBusProvider] Failed to connect to Redis at ${redactConnectionUrl(config.URL)}: ${errorMessage(error)}`);
|
|
292
457
|
}
|
|
293
|
-
const
|
|
458
|
+
const eventBusRuntime = createRedisEventBusRuntime({
|
|
294
459
|
publisher,
|
|
295
460
|
subscriber,
|
|
296
461
|
channelPrefix: configuredChannelPrefix,
|
|
297
462
|
instrumentation: ports,
|
|
298
463
|
});
|
|
464
|
+
const eventBus = eventBusRuntime.eventBus;
|
|
299
465
|
return {
|
|
300
466
|
ports: {
|
|
301
467
|
eventBus,
|
|
@@ -307,6 +473,7 @@ export function createRedisEventBusProvider(options = {}) {
|
|
|
307
473
|
},
|
|
308
474
|
},
|
|
309
475
|
async stop() {
|
|
476
|
+
eventBusRuntime.stop();
|
|
310
477
|
try {
|
|
311
478
|
await subscriber.quit();
|
|
312
479
|
}
|
|
@@ -319,6 +486,10 @@ export function createRedisEventBusProvider(options = {}) {
|
|
|
319
486
|
catch {
|
|
320
487
|
publisher.disconnect();
|
|
321
488
|
}
|
|
489
|
+
if (observeConnectionErrors) {
|
|
490
|
+
publisher.off("error", reportPublisherConnectionError);
|
|
491
|
+
subscriber.off("error", reportSubscriberConnectionError);
|
|
492
|
+
}
|
|
322
493
|
},
|
|
323
494
|
};
|
|
324
495
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beignet/provider-event-bus-redis",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Redis Pub/Sub event bus provider for Beignet - implements EventBusPort for cross-process best-effort delivery",
|
|
6
6
|
"main": "./dist/index.js",
|
package/src/index.ts
CHANGED
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
type ProviderInstrumentationTarget,
|
|
18
18
|
type ServiceProvider,
|
|
19
19
|
} from "@beignet/core/providers";
|
|
20
|
+
import {
|
|
21
|
+
captureTraceCarrier,
|
|
22
|
+
parseTraceCarrier,
|
|
23
|
+
type TraceCarrier,
|
|
24
|
+
} from "@beignet/core/tracing";
|
|
20
25
|
import { Redis } from "ioredis";
|
|
21
26
|
import { z } from "zod";
|
|
22
27
|
|
|
@@ -25,6 +30,8 @@ const DEFAULT_MAX_RETRIES_PER_REQUEST = 2;
|
|
|
25
30
|
const DEFAULT_CONNECT_MAX_ATTEMPTS = 3;
|
|
26
31
|
const DEFAULT_CHANNEL_PREFIX = "beignet:event-bus:";
|
|
27
32
|
const RECONNECT_BACKOFF_CAP_MS = 2000;
|
|
33
|
+
const SUBSCRIPTION_RETRY_BASE_MS = 100;
|
|
34
|
+
const SUBSCRIPTION_RETRY_CAP_MS = 2000;
|
|
28
35
|
|
|
29
36
|
const NumberString = z.union([
|
|
30
37
|
z
|
|
@@ -154,6 +161,13 @@ function reconnectBackoff(attempt: number): number {
|
|
|
154
161
|
return Math.min(2 ** attempt * 100, RECONNECT_BACKOFF_CAP_MS);
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
function subscriptionRetryBackoff(attempt: number): number {
|
|
165
|
+
return Math.min(
|
|
166
|
+
SUBSCRIPTION_RETRY_BASE_MS * 2 ** Math.max(0, attempt - 1),
|
|
167
|
+
SUBSCRIPTION_RETRY_CAP_MS,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
157
171
|
function createRetryStrategy(connectMaxAttempts: number): {
|
|
158
172
|
strategy: (attempt: number) => number | null;
|
|
159
173
|
markConnected: () => void;
|
|
@@ -224,15 +238,31 @@ async function checkRedisEventBusHealth(
|
|
|
224
238
|
}
|
|
225
239
|
}
|
|
226
240
|
|
|
227
|
-
|
|
241
|
+
interface RedisEventBusRuntime {
|
|
242
|
+
eventBus: EventBusPort;
|
|
243
|
+
stop(): void;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function createRedisEventBusRuntime(
|
|
228
247
|
options: CreateRedisEventBusOptions,
|
|
229
|
-
):
|
|
248
|
+
): RedisEventBusRuntime {
|
|
230
249
|
const channelPrefix = options.channelPrefix ?? DEFAULT_CHANNEL_PREFIX;
|
|
231
250
|
const handlers = new Map<
|
|
232
251
|
string,
|
|
233
|
-
Set<
|
|
252
|
+
Set<
|
|
253
|
+
(
|
|
254
|
+
payload: unknown,
|
|
255
|
+
options?: { trace?: TraceCarrier },
|
|
256
|
+
) => void | Promise<void>
|
|
257
|
+
>
|
|
258
|
+
>();
|
|
259
|
+
const subscribedChannels = new Map<string, symbol>();
|
|
260
|
+
const subscriptionRetryAttempts = new Map<string, number>();
|
|
261
|
+
const subscriptionRetryTimers = new Map<
|
|
262
|
+
string,
|
|
263
|
+
ReturnType<typeof setTimeout>
|
|
234
264
|
>();
|
|
235
|
-
|
|
265
|
+
let stopped = false;
|
|
236
266
|
const instrumentation = createProviderInstrumentation(
|
|
237
267
|
options.instrumentation,
|
|
238
268
|
{
|
|
@@ -241,11 +271,37 @@ export function createRedisEventBus(
|
|
|
241
271
|
},
|
|
242
272
|
);
|
|
243
273
|
|
|
244
|
-
const reportSubscriberError = (
|
|
274
|
+
const reportSubscriberError = (
|
|
275
|
+
error: unknown,
|
|
276
|
+
details: {
|
|
277
|
+
operation: "message" | "subscribe" | "unsubscribe";
|
|
278
|
+
channel?: string;
|
|
279
|
+
eventName?: string;
|
|
280
|
+
},
|
|
281
|
+
) => {
|
|
282
|
+
instrumentation.custom({
|
|
283
|
+
name:
|
|
284
|
+
details.operation === "message"
|
|
285
|
+
? "eventBus.message.failed"
|
|
286
|
+
: "eventBus.subscription.failed",
|
|
287
|
+
label:
|
|
288
|
+
details.operation === "message"
|
|
289
|
+
? "Event message failed"
|
|
290
|
+
: "Event subscription failed",
|
|
291
|
+
summary:
|
|
292
|
+
details.eventName ?? details.channel ?? "Redis event bus subscriber",
|
|
293
|
+
details: {
|
|
294
|
+
...details,
|
|
295
|
+
error: errorMessage(error),
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
|
|
245
299
|
try {
|
|
246
|
-
options.onSubscriberError?.(error)
|
|
300
|
+
Promise.resolve(options.onSubscriberError?.(error)).catch(
|
|
301
|
+
() => undefined,
|
|
302
|
+
);
|
|
247
303
|
} catch {
|
|
248
|
-
// Error callbacks should not create
|
|
304
|
+
// Error callbacks should not replace or create another failure.
|
|
249
305
|
}
|
|
250
306
|
};
|
|
251
307
|
|
|
@@ -265,9 +321,11 @@ export function createRedisEventBus(
|
|
|
265
321
|
});
|
|
266
322
|
|
|
267
323
|
try {
|
|
268
|
-
|
|
324
|
+
Promise.resolve(
|
|
325
|
+
options.onHandlerError?.(error, eventName, payload),
|
|
326
|
+
).catch(() => undefined);
|
|
269
327
|
} catch {
|
|
270
|
-
// Error callbacks should not create
|
|
328
|
+
// Error callbacks should not replace or create another failure.
|
|
271
329
|
}
|
|
272
330
|
};
|
|
273
331
|
|
|
@@ -279,6 +337,7 @@ export function createRedisEventBus(
|
|
|
279
337
|
if (!eventHandlers || eventHandlers.size === 0) return;
|
|
280
338
|
|
|
281
339
|
let payload: unknown;
|
|
340
|
+
let trace: TraceCarrier | undefined;
|
|
282
341
|
try {
|
|
283
342
|
const parsed = safeJsonParse(message);
|
|
284
343
|
if (
|
|
@@ -288,9 +347,15 @@ export function createRedisEventBus(
|
|
|
288
347
|
) {
|
|
289
348
|
throw new Error("Redis event bus message is missing a payload field.");
|
|
290
349
|
}
|
|
291
|
-
|
|
350
|
+
const envelope = parsed as { payload: unknown; trace?: unknown };
|
|
351
|
+
payload = envelope.payload;
|
|
352
|
+
trace = parseTraceCarrier(envelope.trace);
|
|
292
353
|
} catch (error) {
|
|
293
|
-
reportSubscriberError(error
|
|
354
|
+
reportSubscriberError(error, {
|
|
355
|
+
operation: "message",
|
|
356
|
+
channel,
|
|
357
|
+
eventName,
|
|
358
|
+
});
|
|
294
359
|
return;
|
|
295
360
|
}
|
|
296
361
|
|
|
@@ -303,9 +368,11 @@ export function createRedisEventBus(
|
|
|
303
368
|
|
|
304
369
|
for (const handler of [...eventHandlers]) {
|
|
305
370
|
try {
|
|
306
|
-
Promise.resolve(handler(payload)).catch(
|
|
307
|
-
|
|
308
|
-
|
|
371
|
+
Promise.resolve(handler(payload, trace ? { trace } : undefined)).catch(
|
|
372
|
+
(error: unknown) => {
|
|
373
|
+
reportHandlerError(error, eventName, payload);
|
|
374
|
+
},
|
|
375
|
+
);
|
|
309
376
|
} catch (error) {
|
|
310
377
|
reportHandlerError(error, eventName, payload);
|
|
311
378
|
}
|
|
@@ -314,40 +381,126 @@ export function createRedisEventBus(
|
|
|
314
381
|
|
|
315
382
|
options.subscriber.on("message", messageHandler);
|
|
316
383
|
|
|
317
|
-
const
|
|
384
|
+
const scheduleSubscriptionRetry = (eventName: string) => {
|
|
318
385
|
const channel = channelForEvent(channelPrefix, eventName);
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
386
|
+
if (
|
|
387
|
+
stopped ||
|
|
388
|
+
subscriptionRetryTimers.has(channel) ||
|
|
389
|
+
!handlers.get(eventName)?.size
|
|
390
|
+
) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const retryAttempt = (subscriptionRetryAttempts.get(channel) ?? 0) + 1;
|
|
395
|
+
subscriptionRetryAttempts.set(channel, retryAttempt);
|
|
396
|
+
const timer = setTimeout(() => {
|
|
397
|
+
subscriptionRetryTimers.delete(channel);
|
|
398
|
+
ensureSubscribed(eventName);
|
|
399
|
+
}, subscriptionRetryBackoff(retryAttempt));
|
|
400
|
+
timer.unref?.();
|
|
401
|
+
subscriptionRetryTimers.set(channel, timer);
|
|
325
402
|
};
|
|
326
403
|
|
|
327
|
-
const
|
|
404
|
+
const ensureSubscribed = (eventName: string) => {
|
|
328
405
|
const channel = channelForEvent(channelPrefix, eventName);
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
406
|
+
if (
|
|
407
|
+
stopped ||
|
|
408
|
+
subscribedChannels.has(channel) ||
|
|
409
|
+
subscriptionRetryTimers.has(channel)
|
|
410
|
+
) {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const attempt = Symbol(channel);
|
|
414
|
+
subscribedChannels.set(channel, attempt);
|
|
415
|
+
|
|
416
|
+
const onFailure = (error: unknown) => {
|
|
417
|
+
if (subscribedChannels.get(channel) === attempt) {
|
|
418
|
+
subscribedChannels.delete(channel);
|
|
419
|
+
scheduleSubscriptionRetry(eventName);
|
|
420
|
+
}
|
|
421
|
+
reportSubscriberError(error, {
|
|
422
|
+
operation: "subscribe",
|
|
423
|
+
channel,
|
|
424
|
+
eventName,
|
|
425
|
+
});
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
Promise.resolve(options.subscriber.subscribe(channel)).then(() => {
|
|
430
|
+
if (subscribedChannels.get(channel) === attempt) {
|
|
431
|
+
subscriptionRetryAttempts.delete(channel);
|
|
432
|
+
}
|
|
433
|
+
}, onFailure);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
onFailure(error);
|
|
436
|
+
}
|
|
333
437
|
};
|
|
334
438
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
439
|
+
const unsubscribeChannel = (eventName: string) => {
|
|
440
|
+
const channel = channelForEvent(channelPrefix, eventName);
|
|
441
|
+
const retryTimer = subscriptionRetryTimers.get(channel);
|
|
442
|
+
if (retryTimer) {
|
|
443
|
+
clearTimeout(retryTimer);
|
|
444
|
+
subscriptionRetryTimers.delete(channel);
|
|
445
|
+
}
|
|
446
|
+
subscriptionRetryAttempts.delete(channel);
|
|
447
|
+
if (!subscribedChannels.has(channel)) return;
|
|
448
|
+
subscribedChannels.delete(channel);
|
|
449
|
+
|
|
450
|
+
const onFailure = (error: unknown) => {
|
|
451
|
+
reportSubscriberError(error, {
|
|
452
|
+
operation: "unsubscribe",
|
|
453
|
+
channel,
|
|
454
|
+
eventName,
|
|
340
455
|
});
|
|
456
|
+
};
|
|
341
457
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
);
|
|
458
|
+
try {
|
|
459
|
+
Promise.resolve(options.subscriber.unsubscribe(channel)).catch(onFailure);
|
|
460
|
+
} catch (error) {
|
|
461
|
+
onFailure(error);
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const eventBus: EventBusPort = {
|
|
466
|
+
async publish(event, payload, publishOptions) {
|
|
467
|
+
const trace =
|
|
468
|
+
parseTraceCarrier(publishOptions?.trace) ??
|
|
469
|
+
captureTraceCarrier(options.instrumentation);
|
|
470
|
+
try {
|
|
471
|
+
await options.publisher.publish(
|
|
472
|
+
channelForEvent(channelPrefix, event.name),
|
|
473
|
+
JSON.stringify({
|
|
474
|
+
eventName: event.name,
|
|
475
|
+
payload,
|
|
476
|
+
...(trace ? { trace } : {}),
|
|
477
|
+
}),
|
|
478
|
+
);
|
|
479
|
+
instrumentation.record({
|
|
480
|
+
type: "eventBus",
|
|
481
|
+
eventName: event.name,
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
instrumentation.custom({
|
|
485
|
+
name: "eventBus.publish.failed",
|
|
486
|
+
label: "Event publish failed",
|
|
487
|
+
summary: `Publish failed for "${event.name}"`,
|
|
488
|
+
details: {
|
|
489
|
+
operation: "publish",
|
|
490
|
+
eventName: event.name,
|
|
491
|
+
error: errorMessage(error),
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
throw error;
|
|
495
|
+
}
|
|
346
496
|
},
|
|
347
497
|
|
|
348
498
|
subscribe<E extends DomainEventDef>(
|
|
349
499
|
event: E,
|
|
350
|
-
handler: (
|
|
500
|
+
handler: (
|
|
501
|
+
payload: InferEventPayload<E>,
|
|
502
|
+
options?: { trace?: TraceCarrier },
|
|
503
|
+
) => void | Promise<void>,
|
|
351
504
|
) {
|
|
352
505
|
let eventHandlers = handlers.get(event.name);
|
|
353
506
|
if (!eventHandlers) {
|
|
@@ -355,14 +508,22 @@ export function createRedisEventBus(
|
|
|
355
508
|
handlers.set(event.name, eventHandlers);
|
|
356
509
|
}
|
|
357
510
|
|
|
358
|
-
eventHandlers.add(
|
|
511
|
+
eventHandlers.add(
|
|
512
|
+
handler as unknown as (
|
|
513
|
+
payload: unknown,
|
|
514
|
+
options?: { trace?: TraceCarrier },
|
|
515
|
+
) => void | Promise<void>,
|
|
516
|
+
);
|
|
359
517
|
ensureSubscribed(event.name);
|
|
360
518
|
|
|
361
519
|
return () => {
|
|
362
520
|
const currentHandlers = handlers.get(event.name);
|
|
363
521
|
if (!currentHandlers) return;
|
|
364
522
|
currentHandlers.delete(
|
|
365
|
-
handler as
|
|
523
|
+
handler as unknown as (
|
|
524
|
+
payload: unknown,
|
|
525
|
+
options?: { trace?: TraceCarrier },
|
|
526
|
+
) => void | Promise<void>,
|
|
366
527
|
);
|
|
367
528
|
if (currentHandlers.size === 0) {
|
|
368
529
|
handlers.delete(event.name);
|
|
@@ -371,6 +532,31 @@ export function createRedisEventBus(
|
|
|
371
532
|
};
|
|
372
533
|
},
|
|
373
534
|
};
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
eventBus,
|
|
538
|
+
stop() {
|
|
539
|
+
stopped = true;
|
|
540
|
+
for (const timer of subscriptionRetryTimers.values()) {
|
|
541
|
+
clearTimeout(timer);
|
|
542
|
+
}
|
|
543
|
+
subscriptionRetryTimers.clear();
|
|
544
|
+
subscriptionRetryAttempts.clear();
|
|
545
|
+
subscribedChannels.clear();
|
|
546
|
+
handlers.clear();
|
|
547
|
+
if (options.subscriber.off) {
|
|
548
|
+
options.subscriber.off("message", messageHandler);
|
|
549
|
+
} else {
|
|
550
|
+
options.subscriber.removeListener?.("message", messageHandler);
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function createRedisEventBus(
|
|
557
|
+
options: CreateRedisEventBusOptions,
|
|
558
|
+
): EventBusPort {
|
|
559
|
+
return createRedisEventBusRuntime(options).eventBus;
|
|
374
560
|
}
|
|
375
561
|
|
|
376
562
|
export function createRedisEventBusProvider(
|
|
@@ -443,6 +629,39 @@ export function createRedisEventBusProvider(
|
|
|
443
629
|
...redisOptions,
|
|
444
630
|
retryStrategy: options.retryStrategy ?? subscriberRetry.strategy,
|
|
445
631
|
});
|
|
632
|
+
const connectionInstrumentation = createProviderInstrumentation(ports, {
|
|
633
|
+
providerName: "event-bus-redis",
|
|
634
|
+
watcher: "eventBus",
|
|
635
|
+
});
|
|
636
|
+
const reportPublisherConnectionError = (error: unknown) => {
|
|
637
|
+
connectionInstrumentation.custom({
|
|
638
|
+
name: "eventBus.connection.failed",
|
|
639
|
+
label: "Event bus connection failed",
|
|
640
|
+
summary: "Redis event bus publisher connection failed",
|
|
641
|
+
details: {
|
|
642
|
+
operation: "connection",
|
|
643
|
+
role: "publisher",
|
|
644
|
+
error: errorMessage(error),
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
};
|
|
648
|
+
const reportSubscriberConnectionError = (error: unknown) => {
|
|
649
|
+
connectionInstrumentation.custom({
|
|
650
|
+
name: "eventBus.connection.failed",
|
|
651
|
+
label: "Event bus connection failed",
|
|
652
|
+
summary: "Redis event bus subscriber connection failed",
|
|
653
|
+
details: {
|
|
654
|
+
operation: "connection",
|
|
655
|
+
role: "subscriber",
|
|
656
|
+
error: errorMessage(error),
|
|
657
|
+
},
|
|
658
|
+
});
|
|
659
|
+
};
|
|
660
|
+
const observeConnectionErrors = connectionInstrumentation.isEnabled();
|
|
661
|
+
if (observeConnectionErrors) {
|
|
662
|
+
publisher.on("error", reportPublisherConnectionError);
|
|
663
|
+
subscriber.on("error", reportSubscriberConnectionError);
|
|
664
|
+
}
|
|
446
665
|
|
|
447
666
|
try {
|
|
448
667
|
await publisher.connect();
|
|
@@ -450,6 +669,10 @@ export function createRedisEventBusProvider(
|
|
|
450
669
|
await subscriber.connect();
|
|
451
670
|
subscriberRetry.markConnected();
|
|
452
671
|
} catch (error) {
|
|
672
|
+
if (observeConnectionErrors) {
|
|
673
|
+
publisher.off("error", reportPublisherConnectionError);
|
|
674
|
+
subscriber.off("error", reportSubscriberConnectionError);
|
|
675
|
+
}
|
|
453
676
|
publisher.disconnect();
|
|
454
677
|
subscriber.disconnect();
|
|
455
678
|
throw new Error(
|
|
@@ -459,12 +682,13 @@ export function createRedisEventBusProvider(
|
|
|
459
682
|
);
|
|
460
683
|
}
|
|
461
684
|
|
|
462
|
-
const
|
|
685
|
+
const eventBusRuntime = createRedisEventBusRuntime({
|
|
463
686
|
publisher,
|
|
464
687
|
subscriber,
|
|
465
688
|
channelPrefix: configuredChannelPrefix,
|
|
466
689
|
instrumentation: ports,
|
|
467
690
|
});
|
|
691
|
+
const eventBus = eventBusRuntime.eventBus;
|
|
468
692
|
|
|
469
693
|
return {
|
|
470
694
|
ports: {
|
|
@@ -482,6 +706,7 @@ export function createRedisEventBusProvider(
|
|
|
482
706
|
},
|
|
483
707
|
} satisfies RedisEventBusProviderPorts,
|
|
484
708
|
async stop() {
|
|
709
|
+
eventBusRuntime.stop();
|
|
485
710
|
try {
|
|
486
711
|
await subscriber.quit();
|
|
487
712
|
} catch {
|
|
@@ -492,6 +717,10 @@ export function createRedisEventBusProvider(
|
|
|
492
717
|
} catch {
|
|
493
718
|
publisher.disconnect();
|
|
494
719
|
}
|
|
720
|
+
if (observeConnectionErrors) {
|
|
721
|
+
publisher.off("error", reportPublisherConnectionError);
|
|
722
|
+
subscriber.off("error", reportSubscriberConnectionError);
|
|
723
|
+
}
|
|
495
724
|
},
|
|
496
725
|
};
|
|
497
726
|
},
|