@voltro/plugin-broadcast 0.83.1 → 0.85.0

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.
@@ -5,66 +5,10 @@ property of its respective copyright holders and is used under the terms of
5
5
  its license. This file is provided for attribution; it grants no rights in
6
6
  @voltro/plugin-broadcast itself, which is proprietary (see LICENSE).
7
7
 
8
- Generated from the resolved runtime dependency closure (21 packages).
8
+ Generated from the resolved runtime dependency closure (19 packages).
9
9
 
10
10
  ---
11
11
 
12
- ## @effect/experimental@0.61.1
13
-
14
- License: MIT
15
-
16
- ```
17
- MIT License
18
-
19
- Copyright (c) 2023-present The Contributors
20
-
21
- Permission is hereby granted, free of charge, to any person obtaining a copy
22
- of this software and associated documentation files (the "Software"), to deal
23
- in the Software without restriction, including without limitation the rights
24
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
- copies of the Software, and to permit persons to whom the Software is
26
- furnished to do so, subject to the following conditions:
27
-
28
- The above copyright notice and this permission notice shall be included in all
29
- copies or substantial portions of the Software.
30
-
31
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
- SOFTWARE.
38
- ```
39
-
40
- ## @effect/sql@0.52.1
41
-
42
- License: MIT
43
-
44
- ```
45
- MIT License
46
-
47
- Copyright (c) 2023-present The Contributors
48
-
49
- Permission is hereby granted, free of charge, to any person obtaining a copy
50
- of this software and associated documentation files (the "Software"), to deal
51
- in the Software without restriction, including without limitation the rights
52
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
- copies of the Software, and to permit persons to whom the Software is
54
- furnished to do so, subject to the following conditions:
55
-
56
- The above copyright notice and this permission notice shall be included in all
57
- copies or substantial portions of the Software.
58
-
59
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
65
- SOFTWARE.
66
- ```
67
-
68
12
  ## @ioredis/commands@1.10.0
69
13
 
70
14
  License: MIT
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { ChangeEvent } from '@voltro/database';
2
2
  import { Effect } from 'effect';
3
3
  import { Schema } from 'effect';
4
4
  import { VoltroPlugin } from '@voltro/protocol';
5
+ import { YieldableError } from 'effect/Cause';
5
6
 
6
7
  /**
7
8
  * Wire a store to a broadcast provider. Publishes local changes outward
@@ -40,6 +41,9 @@ export declare interface AttachBroadcastBusOptions {
40
41
  * embedder) should still say what it lost.
41
42
  */
42
43
  readonly onGap?: (gap: BroadcastGap) => void;
44
+ /** Bounded outbound buffering and broker/shutdown deadlines. Defaults:
45
+ * 1024 messages, 8 MiB, 5s publish, 1s shutdown. Overflow signals peer resync. */
46
+ readonly publishQueue?: BroadcastPublishQueueOptions;
43
47
  }
44
48
 
45
49
  /**
@@ -76,6 +80,9 @@ export declare type BroadcastChannelKind = 'changes' | 'events' | 'members' | 'p
76
80
  * into every OTHER replica's store emitter.
77
81
  */
78
82
  export declare interface BroadcastEnvelope {
83
+ /** Control delivery: refresh live queries rather than inject `event`.
84
+ * Sent after outbound loss, including when no later mutation occurs. */
85
+ readonly resync?: true;
79
86
  readonly origin: string;
80
87
  readonly event: ChangeEvent;
81
88
  /**
@@ -132,14 +139,12 @@ export declare interface BroadcastEnvelope {
132
139
  export declare class BroadcastError extends BroadcastError_base {
133
140
  }
134
141
 
135
- declare const BroadcastError_base: Schema.TaggedErrorClass<BroadcastError, "BroadcastError", {
136
- readonly _tag: Schema.tag<"BroadcastError">;
137
- } & {
138
- provider: typeof Schema.String;
139
- message: typeof Schema.String;
140
- transient: typeof Schema.Boolean;
141
- cause: Schema.optional<typeof Schema.Unknown>;
142
- }>;
142
+ declare const BroadcastError_base: Schema.Class<BroadcastError, Schema.TaggedStruct<"BroadcastError", {
143
+ readonly provider: Schema.String;
144
+ readonly message: Schema.String;
145
+ readonly transient: Schema.Boolean;
146
+ readonly cause: Schema.optional<Schema.Unknown>;
147
+ }>, YieldableError>;
143
148
 
144
149
  /**
145
150
  * A proven — or presumed — hole in what this replica received.
@@ -274,6 +279,13 @@ export declare interface BroadcastProvider {
274
279
  /** Provider id understood by `resolveBroadcastProvider`. */
275
280
  export declare type BroadcastProviderName = 'redis' | 'nats' | 'memory';
276
281
 
282
+ export declare interface BroadcastPublishQueueOptions {
283
+ readonly maxMessages?: number;
284
+ readonly maxBytes?: number;
285
+ readonly timeoutMs?: number;
286
+ readonly shutdownTimeoutMs?: number;
287
+ }
288
+
277
289
  /** The minimal store surface the bus drives — a subset of `DataStore` so
278
290
  * the bus stays decoupled from the concrete store classes. */
279
291
  export declare interface BroadcastStore {
package/dist/index.js CHANGED
@@ -50,24 +50,28 @@ var i = "voltro", a = (e) => e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-"
50
50
  let t = h.get(e);
51
51
  return t || (t = { handlers: /* @__PURE__ */ new Map() }, h.set(e, t)), t;
52
52
  }, _ = (e) => {
53
- h.get(e)?.handlers.clear();
53
+ h.delete(e);
54
54
  }, v = (t = `default-${Math.random().toString(36).slice(2)}`) => {
55
- let n = g(t);
55
+ let n = /* @__PURE__ */ new Set();
56
56
  return {
57
57
  name: "memory",
58
- publish: (t, r) => e.sync(() => {
59
- let e = n.handlers.get(t);
58
+ publish: (n, r) => e.sync(() => {
59
+ let e = h.get(t)?.handlers.get(n);
60
60
  if (e) for (let t of e) try {
61
61
  t(r);
62
62
  } catch {}
63
63
  }),
64
- subscribe: (t, r) => e.sync(() => {
65
- let e = n.handlers.get(t) ?? /* @__PURE__ */ new Set();
66
- return e.add(r), n.handlers.set(t, e), () => {
67
- e.delete(r);
64
+ subscribe: (r, i) => e.sync(() => {
65
+ let e = g(t), a = e.handlers.get(r) ?? /* @__PURE__ */ new Set(), o = (e) => i(e);
66
+ a.add(o), e.handlers.set(r, a);
67
+ let s = () => {
68
+ n.delete(s), a.delete(o), a.size === 0 && e.handlers.get(r) === a && e.handlers.delete(r), e.handlers.size === 0 && h.get(t) === e && h.delete(t);
68
69
  };
70
+ return n.add(s), s;
69
71
  }),
70
- close: () => e.void
72
+ close: () => e.sync(() => {
73
+ for (let e of n) e();
74
+ })
71
75
  };
72
76
  }, y = (t) => {
73
77
  let n = null, r = m(), i = !0, a = () => n || (n = (async () => {
@@ -294,24 +298,87 @@ var i = "voltro", a = (e) => e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-"
294
298
  }, O = (e) => {
295
299
  for (let t of e) if (k(t)) return t;
296
300
  return null;
297
- }, k = (e) => typeof e.broadcast == "object" && e.broadcast !== null && typeof e.broadcast.provider == "object", A = ({ origin: e, ...t }) => t, j = (e) => Math.min(500 * 2 ** Math.min(Math.max(e, 1) - 1, 5), 1e4), M = {
301
+ }, k = (e) => typeof e.broadcast == "object" && e.broadcast !== null && typeof e.broadcast.provider == "object", A = (t, n, r, i, a = {}, o = () => {}) => {
302
+ let s = a.maxMessages ?? 1024, c = a.maxBytes ?? 8388608, l = a.timeoutMs ?? 5e3, u = a.shutdownTimeoutMs ?? 1e3;
303
+ for (let [e, t] of Object.entries({
304
+ maxMessages: s,
305
+ maxBytes: c,
306
+ timeoutMs: l,
307
+ shutdownTimeoutMs: u
308
+ })) if (!Number.isSafeInteger(t) || t < 1) throw Error(`broadcast ${e} must be a positive safe integer`);
309
+ let d = [], f = 0, p = 0, m = !1, h = 0, g = !1, _ = !1, v, y, b = !1, x, S = /* @__PURE__ */ new Set(), C = () => {
310
+ for (let e of S) e();
311
+ S.clear();
312
+ }, w = (e) => {
313
+ m || i(e), m = !0;
314
+ }, T = () => {
315
+ if (g || b || v !== void 0) return;
316
+ let i = d[f];
317
+ if (!i && !m) {
318
+ C();
319
+ return;
320
+ }
321
+ let a = h, s = i?.payload ?? r(a);
322
+ i && (d[f] = void 0, f++, f * 2 >= d.length && (d = d.slice(f), f = 0)), x = new AbortController(), b = !0;
323
+ let c = setTimeout(() => {
324
+ w("publish timed out; peers need a resync");
325
+ }, l);
326
+ y = e.runPromise(t.publish(n, s), { signal: x.signal }).then(() => {
327
+ g || o(), !i && h === a && (m = !1);
328
+ }, () => {
329
+ g || (w("publish failed — cross-replica fan-out degraded, local reactivity unaffected; peers need a resync"), v = setTimeout(() => {
330
+ v = void 0, T();
331
+ }, 500));
332
+ }).finally(() => {
333
+ clearTimeout(c), i && (p -= i.bytes), y = void 0, b = !1, x = void 0, g ? C() : T();
334
+ });
335
+ };
336
+ return {
337
+ enqueue: (e, t) => {
338
+ if (_ || g) return;
339
+ if (h = t, m || d.length - f + +!!b >= s) {
340
+ w("publish queue full; peers need a resync"), T();
341
+ return;
342
+ }
343
+ let n = e(), r = Buffer.byteLength(n, "utf8");
344
+ if (p + r > c) {
345
+ w("publish byte budget exceeded; peers need a resync"), T();
346
+ return;
347
+ }
348
+ p += r, d.push({
349
+ payload: n,
350
+ bytes: r
351
+ }), T();
352
+ },
353
+ close: async () => {
354
+ _ = !0, v !== void 0 && (clearTimeout(v), v = void 0), T();
355
+ let e;
356
+ (y || d.length > f || m) && await new Promise((t) => {
357
+ let n = () => {
358
+ S.delete(n), t();
359
+ };
360
+ S.add(n), e = setTimeout(n, u);
361
+ }), e !== void 0 && clearTimeout(e), g = !0, (y || d.length > f || m) && i("shutdown deadline reached; unsent changes require peer resync"), d = [], f = 0, v !== void 0 && clearTimeout(v), x?.abort(), y && await Promise.race([y, new Promise((e) => setImmediate(e))]), p = 0, C();
362
+ }
363
+ };
364
+ }, j = ({ origin: e, ...t }) => t, M = (e) => Math.min(500 * 2 ** Math.min(Math.max(e, 1) - 1, 5), 1e4), N = {
298
365
  info: () => {},
299
366
  warn: () => {},
300
367
  debug: () => {}
301
- }, N = async (n) => {
302
- let { store: r, provider: i, replicaId: a } = n, o = n.logger ?? M, s = n.channel ?? d, c = !1, l, u = !1, f = 0, p = /* @__PURE__ */ new Map(), m = `${Date.now().toString(36)}.${Math.random().toString(36).slice(2, 10)}`, h = t.gauge("voltro_broadcast_connected").pipe(t.tagged("provider", i.name)), g = t.counter("voltro_broadcast_gaps_total").pipe(t.tagged("provider", i.name)), _ = t.counter("voltro_broadcast_missed_total").pipe(t.tagged("provider", i.name)), v = t.counter("voltro_broadcast_reconnects_total").pipe(t.tagged("provider", i.name)), y = {
368
+ }, P = async (n) => {
369
+ let { store: r, provider: i, replicaId: a } = n, o = n.logger ?? N, s = n.channel ?? d, c = !1, l, u = 0, f = /* @__PURE__ */ new Map(), p = `${Date.now().toString(36)}.${Math.random().toString(36).slice(2, 10)}`, m = t.gauge("voltro_broadcast_connected").pipe(t.withAttributes({ provider: i.name })), h = t.counter("voltro_broadcast_gaps_total").pipe(t.withAttributes({ provider: i.name })), g = t.counter("voltro_broadcast_missed_total").pipe(t.withAttributes({ provider: i.name })), _ = t.counter("voltro_broadcast_reconnects_total").pipe(t.withAttributes({ provider: i.name })), v = {
303
370
  connected: !1,
304
371
  lastReceivedAt: null,
305
372
  lastPublishedAt: null,
306
373
  reconnects: 0,
307
374
  gaps: 0,
308
375
  missed: 0
309
- }, b = (n) => {
310
- y.connected = n, e.runSync(t.set(h, +!!n));
376
+ }, y = (n) => {
377
+ v.connected = n, e.runSync(t.update(m, +!!n));
311
378
  };
312
- b(!1);
313
- let x = (r) => {
314
- y.gaps += 1, e.runSync(t.increment(g)), r.missed !== void 0 && r.missed > 0 && (y.missed += r.missed, e.runSync(t.incrementBy(_, r.missed))), o.warn(`broadcast: ${r.reason} — refreshing live queries, which is safe because a query is idempotent`, {
379
+ y(!1);
380
+ let b = (r) => {
381
+ v.gaps += 1, e.runSync(t.update(h, 1)), r.missed !== void 0 && r.missed > 0 && (v.missed += r.missed, e.runSync(t.update(g, r.missed))), o.warn(`broadcast: ${r.reason} — refreshing live queries, which is safe because a query is idempotent`, {
315
382
  ...r.origin === void 0 ? {} : { origin: r.origin },
316
383
  ...r.missed === void 0 ? {} : { missed: r.missed }
317
384
  });
@@ -320,8 +387,9 @@ var i = "voltro", a = (e) => e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-"
320
387
  } catch (e) {
321
388
  o.warn("broadcast: gap recovery threw", { err: e });
322
389
  }
323
- }, S = (e) => {
324
- y.lastReceivedAt = Date.now();
390
+ }, x = (e) => {
391
+ if (w) return;
392
+ v.lastReceivedAt = Date.now();
325
393
  let t;
326
394
  try {
327
395
  t = JSON.parse(e);
@@ -330,35 +398,66 @@ var i = "voltro", a = (e) => e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-"
330
398
  return;
331
399
  }
332
400
  if (t.origin === a || !t.event || typeof t.event != "object") return;
401
+ let n = !1;
333
402
  if (typeof t.n == "number" && Number.isFinite(t.n)) {
334
- let e = t.epoch ?? "", n = p.get(t.origin);
335
- n === void 0 ? p.set(t.origin, {
403
+ let e = t.epoch ?? "", r = f.get(t.origin);
404
+ if (r === void 0) f.set(t.origin, {
336
405
  epoch: e,
337
406
  n: t.n
338
- }) : n.epoch === e ? (t.n > n.n + 1 && x({
339
- reason: `missed ${t.n - n.n - 1} change(s) from ${t.origin}`,
340
- origin: t.origin,
341
- missed: t.n - n.n - 1
342
- }), t.n > n.n && p.set(t.origin, {
343
- epoch: e,
344
- n: t.n
345
- })) : p.set(t.origin, {
407
+ });
408
+ else if (r.epoch !== e) f.set(t.origin, {
346
409
  epoch: e,
347
410
  n: t.n
348
411
  });
412
+ else {
413
+ let i = t.n - r.n - (t.resync === !0 ? 0 : 1);
414
+ i > 0 && (n = !0, b({
415
+ reason: `missed ${i} change(s) from ${t.origin}`,
416
+ origin: t.origin,
417
+ missed: i
418
+ })), t.n > r.n && f.set(t.origin, {
419
+ epoch: e,
420
+ n: t.n
421
+ });
422
+ }
349
423
  }
350
- let n = A(t.event);
351
- c = !0, l = n;
424
+ if (t.resync === !0) {
425
+ n || b({
426
+ reason: `the ${t.origin} publisher lost changes and requested a resync`,
427
+ origin: t.origin
428
+ });
429
+ return;
430
+ }
431
+ let i = j(t.event);
432
+ c = !0, l = i;
352
433
  try {
353
- r.injectExternalChange(n);
434
+ r.injectExternalChange(i);
354
435
  } catch (e) {
355
436
  o.warn("broadcast: inject failed", { err: e });
356
437
  } finally {
357
438
  c = !1, l = void 0;
358
439
  }
359
- }, C, w = !1, T = 0, E = async () => {
440
+ }, S = A(i, s, (e) => JSON.stringify({
441
+ origin: a,
442
+ epoch: p,
443
+ n: e,
444
+ resync: !0,
445
+ event: {
446
+ table: "",
447
+ op: "update",
448
+ old: null,
449
+ new: null
450
+ }
451
+ }), (e) => {
452
+ o.warn(`broadcast: ${e}`, {
453
+ provider: i.name,
454
+ channel: s
455
+ });
456
+ }, n.publishQueue, () => {
457
+ v.lastPublishedAt = Date.now();
458
+ }), C, w = !1, T = 0, E = async () => {
360
459
  try {
361
- return C = await e.runPromise(i.subscribe(s, S)), b(!0), !0;
460
+ return C = await e.runPromise(i.subscribe(s, x)), w ? (C(), C = void 0, !1) : (y(!0), !0);
362
461
  } catch (e) {
363
462
  return T += 1, T === 1 && o.warn("broadcast: could not subscribe — this replica will not receive other replicas' changes yet. Retrying in the background; local reactivity is unaffected.", {
364
463
  provider: i.name,
@@ -370,72 +469,78 @@ var i = "voltro", a = (e) => e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-"
370
469
  await E() || (async () => {
371
470
  let e = Date.now();
372
471
  for (; !w && C === void 0;) {
373
- if (await new Promise((e) => setTimeout(e, j(T))), w) return;
472
+ if (await new Promise((e) => setTimeout(e, M(T))), w) return;
374
473
  if (await E()) {
375
474
  o.info("broadcast: subscribed", {
376
475
  provider: i.name,
377
476
  channel: s,
378
477
  attempts: T
379
- }), x({ reason: `this replica was not subscribed to '${s}' for ${Math.round((Date.now() - e) / 1e3)}s` });
478
+ }), b({ reason: `this replica was not subscribed to '${s}' for ${Math.round((Date.now() - e) / 1e3)}s` });
380
479
  return;
381
480
  }
382
481
  }
383
482
  })();
384
483
  let D = i.onTransportEvent?.((n) => {
385
- if (n.kind === "disconnected") {
386
- b(!1), o.warn("broadcast: transport disconnected — cross-replica fan-out is down until it re-dials", {
484
+ if (!w) {
485
+ if (n.kind === "disconnected") {
486
+ y(!1), o.warn("broadcast: transport disconnected — cross-replica fan-out is down until it re-dials", {
487
+ provider: i.name,
488
+ ...n.detail === void 0 ? {} : { detail: n.detail }
489
+ });
490
+ return;
491
+ }
492
+ y(!0), v.reconnects += 1, e.runSync(t.update(_, 1)), o.warn("broadcast transport reconnected", {
387
493
  provider: i.name,
388
- ...n.detail === void 0 ? {} : { detail: n.detail }
389
- });
390
- return;
494
+ channel: s,
495
+ replicaId: a,
496
+ reconnects: v.reconnects,
497
+ lastReceivedAt: v.lastReceivedAt
498
+ }), b({ reason: `the ${i.name} transport reconnected after an outage` });
391
499
  }
392
- b(!0), y.reconnects += 1, e.runSync(t.increment(v)), o.warn("broadcast transport reconnected", {
393
- provider: i.name,
394
- channel: s,
395
- replicaId: a,
396
- reconnects: y.reconnects,
397
- lastReceivedAt: y.lastReceivedAt
398
- }), x({ reason: `the ${i.name} transport reconnected after an outage` });
399
- }), O = r.onChange((t) => {
400
- if (t.origin === "injected" || c && t === l) return;
401
- f += 1;
402
- let n = {
500
+ }), O = r.onChange((e) => {
501
+ if (e.origin === "injected" || c && e === l) return;
502
+ u += 1;
503
+ let t = {
403
504
  origin: a,
404
- event: t,
405
- n: f,
406
- epoch: m
505
+ event: e,
506
+ n: u,
507
+ epoch: p
407
508
  };
408
- y.lastPublishedAt = Date.now(), e.runPromise(i.publish(s, JSON.stringify(n)).pipe(e.tap(() => e.sync(() => {
409
- u = !1;
410
- })), e.catchAll((t) => e.sync(() => {
411
- u || (u = !0, o.warn("broadcast: publish failed — cross-replica fan-out degraded, local reactivity unaffected", {
412
- provider: i.name,
413
- transient: t.transient,
414
- message: t.message
415
- }));
416
- }))));
509
+ S.enqueue(() => JSON.stringify(t), u);
417
510
  });
418
- return o.info("broadcast bus attached", {
511
+ o.info("broadcast bus attached", {
419
512
  provider: i.name,
420
513
  channel: s,
421
514
  replicaId: a
422
- }), {
515
+ });
516
+ let k;
517
+ return {
423
518
  health: () => ({
424
519
  provider: i.name,
425
520
  channel: s,
426
521
  replicaId: a,
427
- ...y
522
+ ...v
428
523
  }),
429
- close: async () => {
430
- if (!w) {
431
- w = !0, O(), D?.();
432
- try {
433
- C?.();
434
- } catch {}
435
- await e.runPromise(i.close());
524
+ close: () => (k ??= (async () => {
525
+ w = !0, O(), D?.(), y(!1);
526
+ try {
527
+ C?.();
528
+ } catch {}
529
+ await S.close();
530
+ let t = new AbortController(), r, a = e.runPromise(i.close(), { signal: t.signal }).catch((e) => {
531
+ o.warn("broadcast: provider close failed", { error: e });
532
+ });
533
+ try {
534
+ await Promise.race([a, new Promise((e) => {
535
+ r = setTimeout(() => {
536
+ o.warn("broadcast: provider shutdown timed out"), t.abort(), e();
537
+ }, n.publishQueue?.shutdownTimeoutMs ?? 1e3);
538
+ })]);
539
+ } finally {
540
+ r !== void 0 && clearTimeout(r);
436
541
  }
437
- }
542
+ })(), k)
438
543
  };
439
544
  };
440
545
  //#endregion
441
- export { d as BROADCAST_CHANNEL, u as BroadcastError, i as DEFAULT_BROADCAST_NAMESPACE, N as attachBroadcastBus, D as broadcastPlugin, c as channelFor, o as describeNamespaceResolution, l as eventChannelFor, O as getBroadcastPlugin, v as memoryProvider, S as natsProvider, y as redisProvider, _ as resetMemoryBus, s as resolveBroadcastNamespace, w as resolveBroadcastProvider, j as subscribeRetryDelayMs };
546
+ export { d as BROADCAST_CHANNEL, u as BroadcastError, i as DEFAULT_BROADCAST_NAMESPACE, P as attachBroadcastBus, D as broadcastPlugin, c as channelFor, o as describeNamespaceResolution, l as eventChannelFor, O as getBroadcastPlugin, v as memoryProvider, S as natsProvider, y as redisProvider, _ as resetMemoryBus, s as resolveBroadcastNamespace, w as resolveBroadcastProvider, M as subscribeRetryDelayMs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-broadcast",
3
- "version": "0.83.1",
3
+ "version": "0.85.0",
4
4
  "description": "Cross-replica reactivity — a pub/sub message bus (Redis / NATS / memory) that fans out app-mutation ChangeEvents to every replica behind a load balancer. ADDITIVE to inline emit: local reactivity survives a broker outage; cross-replica degrades gracefully. Closes the single-instance gap for every non-postgres dialect (postgres keeps native LISTEN/NOTIFY).",
5
5
  "keywords": [
6
6
  "voltro",
@@ -33,15 +33,15 @@
33
33
  "node": ">=24.0.0"
34
34
  },
35
35
  "dependencies": {
36
- "@voltro/database": "0.83.1",
37
- "@voltro/protocol": "0.83.1"
36
+ "@voltro/database": "0.85.0",
37
+ "@voltro/protocol": "0.85.0"
38
38
  },
39
39
  "optionalDependencies": {
40
40
  "@nats-io/transport-node": "^3.4.0",
41
41
  "ioredis": "^5.11.1"
42
42
  },
43
43
  "peerDependencies": {
44
- "effect": "^3.22.2"
44
+ "effect": "4.0.1"
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public"