cross-tab-worker-databus 0.20.71 → 0.20.86

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.
Files changed (97) hide show
  1. package/CHANGELOG.md +216 -2
  2. package/README.md +8 -0
  3. package/README.zh.md +4 -0
  4. package/dist/centrifuge-protocol.d.ts +59 -26
  5. package/dist/centrifuge-protocol.d.ts.map +1 -1
  6. package/dist/centrifuge-session.d.ts +9 -0
  7. package/dist/centrifuge-session.d.ts.map +1 -1
  8. package/dist/centrifuge.d.ts +12 -2
  9. package/dist/centrifuge.d.ts.map +1 -1
  10. package/dist/centrifuge.js +168 -88
  11. package/dist/centrifuge.js.map +3 -3
  12. package/dist/centrifuge.shared.worker.js +146 -38
  13. package/dist/centrifuge.shared.worker.js.map +3 -3
  14. package/dist/centrifuge.worker.js +140 -33
  15. package/dist/centrifuge.worker.js.map +3 -3
  16. package/dist/{chunk-D2SIT473.js → chunk-SDOV3UHG.js} +1304 -515
  17. package/dist/chunk-SDOV3UHG.js.map +7 -0
  18. package/dist/chunk-TZ7ZP7YD.js +175 -0
  19. package/dist/chunk-TZ7ZP7YD.js.map +7 -0
  20. package/dist/cjs/centrifuge.cjs +1608 -650
  21. package/dist/cjs/centrifuge.cjs.map +4 -4
  22. package/dist/cjs/hooks.cjs +37 -2
  23. package/dist/cjs/hooks.cjs.map +3 -3
  24. package/dist/cjs/index.cjs +1692 -747
  25. package/dist/cjs/index.cjs.map +4 -4
  26. package/dist/cjs/vue.cjs +45 -2
  27. package/dist/cjs/vue.cjs.map +3 -3
  28. package/dist/core/cluster.d.ts +40 -4
  29. package/dist/core/cluster.d.ts.map +1 -1
  30. package/dist/core/data-bus.d.ts +134 -77
  31. package/dist/core/data-bus.d.ts.map +1 -1
  32. package/dist/core/dedup-manager.d.ts +98 -0
  33. package/dist/core/dedup-manager.d.ts.map +1 -0
  34. package/dist/core/environment.d.ts +43 -3
  35. package/dist/core/environment.d.ts.map +1 -1
  36. package/dist/core/replay-manager.d.ts +129 -0
  37. package/dist/core/replay-manager.d.ts.map +1 -0
  38. package/dist/core/replay-persistence.d.ts +2 -1
  39. package/dist/core/replay-persistence.d.ts.map +1 -1
  40. package/dist/core/replay-pruning.d.ts +21 -0
  41. package/dist/core/replay-pruning.d.ts.map +1 -0
  42. package/dist/core/routing.d.ts +22 -3
  43. package/dist/core/routing.d.ts.map +1 -1
  44. package/dist/core/storage-batch.d.ts +0 -4
  45. package/dist/core/storage-batch.d.ts.map +1 -1
  46. package/dist/core/trace.d.ts +55 -15
  47. package/dist/core/trace.d.ts.map +1 -1
  48. package/dist/core/types.d.ts +58 -9
  49. package/dist/core/types.d.ts.map +1 -1
  50. package/dist/core/version.d.ts +2 -0
  51. package/dist/core/version.d.ts.map +1 -0
  52. package/dist/hooks.d.ts +12 -1
  53. package/dist/hooks.d.ts.map +1 -1
  54. package/dist/hooks.js +28 -2
  55. package/dist/hooks.js.map +2 -2
  56. package/dist/index.d.ts +6 -6
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +263 -166
  59. package/dist/index.js.map +3 -3
  60. package/dist/utils/constants.d.ts +170 -0
  61. package/dist/utils/constants.d.ts.map +1 -0
  62. package/dist/utils/error-utils.d.ts +28 -0
  63. package/dist/utils/error-utils.d.ts.map +1 -0
  64. package/dist/utils/metadata.d.ts +16 -0
  65. package/dist/utils/metadata.d.ts.map +1 -0
  66. package/dist/utils/storage-utils.d.ts +24 -0
  67. package/dist/utils/storage-utils.d.ts.map +1 -0
  68. package/dist/utils/validation.d.ts +76 -0
  69. package/dist/utils/validation.d.ts.map +1 -0
  70. package/dist/vue.d.ts +13 -1
  71. package/dist/vue.d.ts.map +1 -1
  72. package/dist/vue.js +36 -2
  73. package/dist/vue.js.map +2 -2
  74. package/dist/websocket.d.ts +6 -1
  75. package/dist/websocket.d.ts.map +1 -1
  76. package/dist/worker-mode.d.ts +6 -2
  77. package/dist/worker-mode.d.ts.map +1 -1
  78. package/docs/README.md +1 -0
  79. package/docs/api.md +135 -4
  80. package/docs/architecture.md +92 -1
  81. package/docs/benchmarks.md +24 -0
  82. package/docs/capabilities.md +24 -3
  83. package/docs/configuration.md +58 -0
  84. package/docs/getting-started.md +35 -0
  85. package/docs/release-checklist.md +28 -5
  86. package/docs/roadmap.md +81 -5
  87. package/docs/zh/README.md +2 -1
  88. package/docs/zh/api.md +134 -4
  89. package/docs/zh/architecture.md +61 -1
  90. package/docs/zh/benchmarks.md +24 -0
  91. package/docs/zh/capabilities.md +21 -3
  92. package/docs/zh/configuration.md +53 -0
  93. package/docs/zh/getting-started.md +35 -0
  94. package/docs/zh/release-checklist.md +29 -6
  95. package/docs/zh/roadmap.md +93 -5
  96. package/package.json +39 -16
  97. package/dist/chunk-D2SIT473.js.map +0 -7
package/dist/cjs/vue.cjs CHANGED
@@ -21,11 +21,25 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var vue_exports = {};
22
22
  __export(vue_exports, {
23
23
  useCrossTabDataBus: () => useCrossTabDataBus,
24
+ useCrossTabHealth: () => useCrossTabHealth,
24
25
  useCrossTabStatus: () => useCrossTabStatus,
25
26
  useCrossTabSubscription: () => useCrossTabSubscription
26
27
  });
27
28
  module.exports = __toCommonJS(vue_exports);
28
29
  var import_vue = require("vue");
30
+
31
+ // src/utils/constants.ts
32
+ var WORKER_STATUS = {
33
+ CONNECTING: "connecting",
34
+ CONNECTED: "connected",
35
+ DISCONNECTED: "disconnected",
36
+ ERROR: "error"
37
+ };
38
+ var DEFAULT_STORAGE_PREFIX = "cross-tab-worker-databus";
39
+ var STORAGE_CHANNEL_PREFIX = `${DEFAULT_STORAGE_PREFIX}:channel:`;
40
+ var TAB_ID_STORAGE_KEY = `${DEFAULT_STORAGE_PREFIX}:tab-id`;
41
+
42
+ // src/vue.ts
29
43
  function useCrossTabDataBus(create, deps = []) {
30
44
  const bus = (0, import_vue.shallowRef)(null);
31
45
  let instance = null;
@@ -49,6 +63,7 @@ function useCrossTabDataBus(create, deps = []) {
49
63
  };
50
64
  (0, import_vue.onMounted)(start);
51
65
  (0, import_vue.onBeforeUnmount)(() => {
66
+ lifecycleGeneration += 1;
52
67
  void stop();
53
68
  });
54
69
  if (deps.length > 0) (0, import_vue.watch)(deps, start);
@@ -83,12 +98,12 @@ function useCrossTabSubscription(bus, topic, handler) {
83
98
  (0, import_vue.onBeforeUnmount)(stop);
84
99
  }
85
100
  function useCrossTabStatus(bus) {
86
- const status = (0, import_vue.ref)("connecting");
101
+ const status = (0, import_vue.ref)(WORKER_STATUS.CONNECTING);
87
102
  let cleanup;
88
103
  (0, import_vue.watch)(bus, (next) => {
89
104
  cleanup?.();
90
105
  cleanup = void 0;
91
- status.value = next?.getStatus() ?? "connecting";
106
+ status.value = next?.getStatus() ?? WORKER_STATUS.CONNECTING;
92
107
  if (next) cleanup = next.onStatus((value) => {
93
108
  status.value = value;
94
109
  });
@@ -96,4 +111,32 @@ function useCrossTabStatus(bus) {
96
111
  (0, import_vue.onBeforeUnmount)(() => cleanup?.());
97
112
  return status;
98
113
  }
114
+ function useCrossTabHealth(bus, options) {
115
+ const health = (0, import_vue.ref)(null);
116
+ let timer = null;
117
+ let cleanups = [];
118
+ const teardown = () => {
119
+ if (timer) clearInterval(timer);
120
+ timer = null;
121
+ for (const cleanup of cleanups) cleanup();
122
+ cleanups = [];
123
+ };
124
+ (0, import_vue.watch)(bus, (next) => {
125
+ teardown();
126
+ if (!next) {
127
+ health.value = null;
128
+ return;
129
+ }
130
+ const refresh = () => {
131
+ health.value = next.getHealthSummary();
132
+ };
133
+ refresh();
134
+ cleanups.push(next.onStatus(refresh));
135
+ cleanups.push(next.onError(refresh));
136
+ const intervalMs = options?.intervalMs ?? 1e3;
137
+ if (intervalMs > 0) timer = setInterval(refresh, intervalMs);
138
+ }, { immediate: true });
139
+ (0, import_vue.onBeforeUnmount)(teardown);
140
+ return health;
141
+ }
99
142
  //# sourceMappingURL=vue.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/vue.ts"],
4
- "sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => { void stop(); });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n let latestHandler = handler;\n const stop = () => { cleanup?.(); cleanup = undefined; currentBus = null; currentTopic = null; };\n const sync = () => {\n const nextBus = bus.value;\n const nextTopic = typeof topic === 'string' ? topic : topic.value;\n if (nextBus === currentBus && currentTopic === nextTopic && cleanup) return;\n stop();\n if (!nextBus) return;\n currentBus = nextBus;\n currentTopic = nextTopic;\n cleanup = nextBus.subscribe(nextTopic, message => latestHandler(message));\n };\n watch(bus, sync, { immediate: true });\n if (typeof topic !== 'string') watch(topic, sync);\n watch(() => handler, value => { latestHandler = value; });\n onBeforeUnmount(stop);\n}\n\nexport function useCrossTabStatus<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>\n): Ref<WorkerStatus> {\n const status = ref<WorkerStatus>('connecting');\n let cleanup: (() => void) | undefined;\n watch(bus, next => {\n cleanup?.(); cleanup = undefined;\n status.value = next?.getStatus() ?? 'connecting';\n if (next) cleanup = next.onStatus(value => { status.value = value; });\n }, { immediate: true });\n onBeforeUnmount(() => cleanup?.());\n return status;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAA6E;AAItE,SAAS,mBACd,QACA,OAAsD,CAAC,GACV;AAC7C,QAAM,UAAM,uBAAmD,IAAI;AACnE,MAAI,WAAmD;AACvD,MAAI,sBAAsB;AAC1B,QAAM,OAAO,YAAY;AAAE,UAAM,UAAU;AAAU,eAAW;AAAM,QAAI,QAAQ;AAAM,QAAI,QAAS,OAAM,QAAQ,KAAK;AAAA,EAAG;AAC3H,QAAM,QAAQ,MAAM;AAClB,UAAM,aAAa,EAAE;AACrB,SAAK,KAAK,EAAE,KAAK,MAAM;AACrB,UAAI,eAAe,oBAAqB;AACxC,YAAM,OAAO,OAAO;AACpB,iBAAW;AACX,UAAI,QAAQ;AACZ,WAAK,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC,CAAC;AAAA,EACH;AACA,4BAAU,KAAK;AACf,kCAAgB,MAAM;AAAE,SAAK,KAAK;AAAA,EAAG,CAAC;AACtC,MAAI,KAAK,SAAS,EAAG,uBAAM,MAAM,KAAK;AACtC,SAAO;AACT;AAEO,SAAS,wBACd,KAAkD,OAClD,SACM;AACN,MAAI,aAAqD;AACzD,MAAI,eAA8B;AAClC,MAAI;AACJ,MAAI,gBAAgB;AACpB,QAAM,OAAO,MAAM;AAAE,cAAU;AAAG,cAAU;AAAW,iBAAa;AAAM,mBAAe;AAAA,EAAM;AAC/F,QAAM,OAAO,MAAM;AACjB,UAAM,UAAU,IAAI;AACpB,UAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,MAAM;AAC5D,QAAI,YAAY,cAAc,iBAAiB,aAAa,QAAS;AACrE,SAAK;AACL,QAAI,CAAC,QAAS;AACd,iBAAa;AACb,mBAAe;AACf,cAAU,QAAQ,UAAU,WAAW,aAAW,cAAc,OAAO,CAAC;AAAA,EAC1E;AACA,wBAAM,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AACpC,MAAI,OAAO,UAAU,SAAU,uBAAM,OAAO,IAAI;AAChD,wBAAM,MAAM,SAAS,WAAS;AAAE,oBAAgB;AAAA,EAAO,CAAC;AACxD,kCAAgB,IAAI;AACtB;AAEO,SAAS,kBACd,KACmB;AACnB,QAAM,aAAS,gBAAkB,YAAY;AAC7C,MAAI;AACJ,wBAAM,KAAK,UAAQ;AACjB,cAAU;AAAG,cAAU;AACvB,WAAO,QAAQ,MAAM,UAAU,KAAK;AACpC,QAAI,KAAM,WAAU,KAAK,SAAS,WAAS;AAAE,aAAO,QAAQ;AAAA,IAAO,CAAC;AAAA,EACtE,GAAG,EAAE,WAAW,KAAK,CAAC;AACtB,kCAAgB,MAAM,UAAU,CAAC;AACjC,SAAO;AACT;",
3
+ "sources": ["../../src/vue.ts", "../../src/utils/constants.ts"],
4
+ "sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => {\n // Bump the generation so a start() still awaiting its stop() sees itself\n // superseded. Without this the pending continuation would run create()\n // after the component is gone, leaving a live bus with no owner to stop\n // it (the React adapter has no such window: its create() is synchronous\n // inside useEffect).\n lifecycleGeneration += 1;\n void stop();\n });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n let latestHandler = handler;\n const stop = () => { cleanup?.(); cleanup = undefined; currentBus = null; currentTopic = null; };\n const sync = () => {\n const nextBus = bus.value;\n const nextTopic = typeof topic === 'string' ? topic : topic.value;\n if (nextBus === currentBus && currentTopic === nextTopic && cleanup) return;\n stop();\n if (!nextBus) return;\n currentBus = nextBus;\n currentTopic = nextTopic;\n cleanup = nextBus.subscribe(nextTopic, message => latestHandler(message));\n };\n watch(bus, sync, { immediate: true });\n if (typeof topic !== 'string') watch(topic, sync);\n watch(() => handler, value => { latestHandler = value; });\n onBeforeUnmount(stop);\n}\n\nexport function useCrossTabStatus<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>\n): Ref<WorkerStatus> {\n const status = ref<WorkerStatus>(WORKER_STATUS.CONNECTING);\n let cleanup: (() => void) | undefined;\n watch(bus, next => {\n cleanup?.(); cleanup = undefined;\n status.value = next?.getStatus() ?? WORKER_STATUS.CONNECTING;\n if (next) cleanup = next.onStatus(value => { status.value = value; });\n }, { immediate: true });\n onBeforeUnmount(() => cleanup?.());\n return status;\n}\n\n/** Options for {@link useCrossTabHealth}. */\nexport interface UseCrossTabHealthOptions {\n /** Polling cadence in ms for the health snapshot. Default 1000; `0` disables\n * polling and relies on status/error events only. */\n intervalMs?: number;\n}\n\n/**\n * Mirror the bus health summary into a Vue ref. `getHealthSummary()` is a\n * snapshot, so the composable polls it on an interval (default 1000 ms) and\n * refreshes on status changes and errors. Returns `null` until the bus exists.\n */\nexport function useCrossTabHealth<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>,\n options?: UseCrossTabHealthOptions\n): Ref<DataBusHealthSummary | null> {\n const health = ref<DataBusHealthSummary | null>(null);\n let timer: ReturnType<typeof setInterval> | null = null;\n let cleanups: Array<() => void> = [];\n const teardown = () => {\n if (timer) clearInterval(timer);\n timer = null;\n for (const cleanup of cleanups) cleanup();\n cleanups = [];\n };\n watch(bus, next => {\n teardown();\n if (!next) {\n health.value = null;\n return;\n }\n const refresh = () => { health.value = next.getHealthSummary(); };\n refresh();\n cleanups.push(next.onStatus(refresh));\n cleanups.push(next.onError(refresh));\n const intervalMs = options?.intervalMs ?? 1_000;\n if (intervalMs > 0) timer = setInterval(refresh, intervalMs);\n }, { immediate: true });\n onBeforeUnmount(teardown);\n return health as Ref<DataBusHealthSummary | null>;\n}\n", "/**\n * \u516C\u5171\u5B57\u7B26\u4E32\u5E38\u91CF \u2014\u2014 \u751F\u547D\u5468\u671F\u72B6\u6001\u3001\u89D2\u8272\u3001\u63A7\u5236\u52A8\u4F5C\u3001\u534F\u8BAE\u6D88\u606F\u7C7B\u578B\u3001\u679A\u4E3E\u4E0E\n * \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u3002\n *\n * \u6240\u6709\u8FD0\u884C\u65F6\u4F7F\u7528\u7684\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u96C6\u4E2D\u5728\u6B64\u4E00\u4EFD\u503C\uFF0C\u7C7B\u578B\u5B9A\u4E49\uFF08src/core/types.ts\n * \u7B49\uFF09\u901A\u8FC7 `(typeof X)[keyof typeof X]` \u4ECE\u8FD9\u4E9B\u5E38\u91CF\u6D3E\u751F\uFF0C\u6BD4\u8F83/switch \u5904\u5F15\u7528\n * \u540C\u4E00\u5BF9\u8C61\u6210\u5458\u3002\u8FD9\u6837\u65E2\u80FD\u6D88\u9664\u6563\u843D\u5728\u5404\u6587\u4EF6\u91CC\u7684\u91CD\u590D\u5B57\u7B26\u4E32\uFF08\u907F\u514D\u5927\u5C0F\u5199\u4E0D\u7EDF\u4E00\n * \u6216\u7B14\u8BEF\uFF09\uFF0C\u53C8\u4FDD\u8BC1\u7C7B\u578B\u4E0E\u503C\u6C38\u4E0D\u9519\u4F4D\u3002\n *\n * ## \u4F7F\u7528\u7EA6\u5B9A\n *\n * - **\u65B0\u589E\u6216\u4FEE\u6539\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u65F6\uFF0C\u5148\u5230\u8FD9\u91CC\u67E5\u627E/\u589E\u8865\uFF0C\u4E0D\u8981\u5728\u4E1A\u52A1\u6587\u4EF6\u91CC\u76F4\u63A5\u5199\n * \u9B54\u6CD5\u5B57\u7B26\u4E32\u3002** \u626B\u63CF\u6B8B\u7559\u5B57\u9762\u91CF\uFF1A`rg \"'(['a-z]+)'\" src/`\u3002\n * - **\u53EA\u7528\u4E8E\u7C7B\u578B\u4F4D\u7F6E\u7684\u5E38\u91CF**\uFF08\u5982 `PERSISTENCE_OPERATION`\uFF09\u5728\u8C03\u7528\u65B9\u7528\n * `import type`\uFF1B**\u5728\u8FD0\u884C\u65F6\u6BD4\u8F83/\u6784\u9020\u4E2D\u4F7F\u7528\u7684**\uFF08\u5982 `WORKER_STATUS.ERROR`\u3001\n * `TRACE_EVENT_TYPE.LIFECYCLE`\uFF09\u5FC5\u987B\u7528\u503C\u5BFC\u5165\uFF0C\u5426\u5219\u4F1A\u62A5 \"cannot be used as\n * a value because it was imported using 'import type'\"\u3002\n * - **\u503C\u6D3E\u751F\u7C7B\u578B**\uFF1A`export type WorkerStatus = (typeof WORKER_STATUS)[keyof\n * typeof WORKER_STATUS]`\u3002\u8FD9\u6837\u65B0\u589E\u679A\u4E3E\u5206\u652F\u65F6\u7C7B\u578B\u81EA\u52A8\u6536\u7A84\uFF0C\u7F16\u8BD1\u5668\u4F1A\u6307\u51FA\n * \u6BCF\u4E2A\u9057\u6F0F\u7684 switch \u5206\u652F\u3002\n * - \u5206\u7EC4\u7684\u987A\u5E8F\uFF08\u72B6\u6001 / \u89D2\u8272 / \u540E\u7AEF / \u6D88\u606F\u7C7B\u578B / \u679A\u4E3E / \u524D\u7F00\uFF09\u4FDD\u6301\u7A33\u5B9A\uFF0C\u65B9\u4FBF\n * \u7EF4\u62A4\u8005\u4E00\u773C\u5B9A\u4F4D\u3002\n */\n\n// ---- \u751F\u547D\u5468\u671F\u72B6\u6001 / \u89D2\u8272 / \u53EF\u89C1\u6027 ----\nexport const WORKER_STATUS = {\n CONNECTING: 'connecting',\n CONNECTED: 'connected',\n DISCONNECTED: 'disconnected',\n ERROR: 'error',\n} as const;\n\nexport const WORKER_ROLE = {\n ACTIVE: 'active',\n STANDBY: 'standby',\n} as const;\n\nexport const TAB_VISIBILITY = {\n VISIBLE: 'visible',\n HIDDEN: 'hidden',\n} as const;\n\n// ---- Worker \u540E\u7AEF\u6A21\u5F0F\u4E0E\u89E3\u6790\u7ED3\u679C\uFF08WorkerMode / WorkerBackend\uFF09----\nexport const WORKER_MODE = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n AUTO: 'auto',\n} as const;\n\nexport const WORKER_BACKEND = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n LOCAL: 'local',\n} as const;\n\n// ---- \u5B58\u50A8\u4E8B\u4EF6\u901A\u9053\u56DE\u9000 ----\nexport const CHANNEL_FALLBACK = {\n NONE: 'none',\n STORAGE_EVENT: 'storage-event',\n} as const;\n\n// ---- Worker / MessagePort / BroadcastChannel \u7684 EventTarget \u4E8B\u4EF6\u540D\u5224\u522B ----\n// MessageEvent.type\uFF08'message' / 'messageerror'\uFF09\u4E0E Worker \u4E0A\u7684 'error' \u4E8B\u4EF6\u540D\uFF0C\n// \u7528\u4E8E\u73AF\u5883\u9002\u914D\u5668\u63A5\u53E3\u7B7E\u540D\u4E0E\u6D4B\u8BD5\u66FF\u8EAB\u7684 addEventListener \u771F\u5047\u5206\u652F\u3002\nexport const EVENT_TYPE = {\n MESSAGE: 'message',\n MESSAGEERROR: 'messageerror',\n ERROR: 'error',\n} as const;\n\n// ---- \u63A7\u5236\u5E73\u9762\u52A8\u4F5C\uFF08WorkerControlAction\uFF09----\nexport const CONTROL_ACTION = {\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n} as const;\n\n// ---- BroadcastChannel \u96C6\u7FA4\u6D88\u606F\u7C7B\u578B ----\nexport const CLUSTER_MESSAGE_TYPE = {\n CONTROL: 'CONTROL',\n EVENT: 'EVENT',\n REGISTRY: 'REGISTRY',\n ROUTE_RELEASED: 'ROUTE_RELEASED',\n} as const;\n\n// ---- \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u4E0E\u4E8B\u4EF6\u540D ----\nexport const DEFAULT_STORAGE_PREFIX = 'cross-tab-worker-databus';\nexport const STORAGE_CHANNEL_PREFIX = `${DEFAULT_STORAGE_PREFIX}:channel:`;\nexport const TAB_ID_STORAGE_KEY = `${DEFAULT_STORAGE_PREFIX}:tab-id`;\nexport const PUBLICATION_EVENT = 'DATABUS_PUBLICATION';\n\n// ---- \u89C4\u8303 JSON \u4FE1\u5C01\u64CD\u4F5C\u7801 ----\nexport const PUBLICATION_ENVELOPE_OP = 'publication';\n\n// ---- trace \u4E8B\u4EF6\u7C7B\u578B ----\nexport const TRACE_EVENT_TYPE = {\n LIFECYCLE: 'lifecycle',\n STATUS: 'status',\n SUBSCRIPTION: 'subscription',\n COORDINATION: 'coordination',\n ERROR: 'error',\n RELIABILITY: 'reliability',\n MESSAGE_METRICS: 'message_metrics',\n} as const;\n\n// ---- trace \u751F\u547D\u5468\u671F\u52A8\u4F5C ----\nexport const TRACE_LIFECYCLE_ACTION = {\n START: 'start',\n STOP: 'stop',\n SUSPEND: 'suspend',\n RESUME: 'resume',\n} as const;\n\n// ---- \u5185\u90E8 handler \u8C03\u7528\u6807\u7B7E\uFF08\u9694\u79BB\u5F02\u5E38\u65F6\u7684\u5206\u7C7B\u6765\u6E90\uFF09----\nexport const INVOKE_LABEL = {\n DISPATCH: 'dispatch',\n STATUS: 'status',\n ERROR_HANDLER: 'error handler',\n} as const;\n\n// ---- trace \u6A21\u5F0F\uFF08DataBusTraceMode\uFF09----\nexport const TRACE_MODE = {\n EVENTS: 'events',\n METRICS: 'metrics',\n ALL: 'all',\n} as const;\n\n// ---- trace \u9519\u8BEF\u6765\u6E90 ----\nexport const TRACE_ERROR_SOURCE = {\n TRANSPORT: 'transport',\n OPERATION: 'operation',\n} as const;\n\n// ---- reliability \u8BCA\u65AD\u64CD\u4F5C ----\nexport const RELIABILITY_OPERATION = {\n TRANSPORT_RECOVERY: 'transport_recovery',\n ROUTE_ACK: 'route_ack',\n ROUTE_MIGRATION: 'route_migration',\n // A re-election that recovered a stranded unconfirmed handoff (previous\n // owner gone, ACK never arrived). Distinct from ROUTE_MIGRATION so trace\n // consumers can tell recoveries apart from routine graceful handoffs.\n ROUTE_MIGRATION_RECOVERY: 'route_migration_recovery',\n PERSISTENCE_CLEANUP: 'persistence_cleanup',\n PERSISTENCE_RETRY: 'persistence_retry',\n DEDUP_SUPPRESSED: 'dedup_suppressed',\n} as const;\n\n// ---- \u81EA\u52A8\u6062\u590D\u5C1D\u8BD5\u7ED3\u679C ----\nexport const RECOVERY_OUTCOME = {\n SCHEDULED: 'scheduled',\n SUCCEEDED: 'succeeded',\n FAILED: 'failed',\n EXHAUSTED: 'exhausted',\n} as const;\n\n// ---- \u8BA2\u9605\u52A8\u4F5C ----\nexport const SUBSCRIPTION_ACTION = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n} as const;\n\n// ---- \u56DE\u653E\u4FEE\u526A\u7B56\u7565 ----\nexport const PRUNE_STRATEGY = {\n COUNT: 'count',\n AGE: 'age',\n BOTH: 'both',\n} as const;\n\n// ---- \u6301\u4E45\u5316\u64CD\u4F5C ----\nexport const PERSISTENCE_OPERATION = {\n LOAD: 'load',\n APPEND: 'append',\n CLEAR: 'clear',\n CLEAR_TOPIC: 'clearTopic',\n CLEAR_BEFORE: 'clearBefore',\n} as const;\n\n// ---- \u6545\u969C\u6765\u6E90\uFF08DataBusFailureSource\uFF09----\nexport const FAILURE_SOURCE = {\n TRANSPORT: 'transport',\n PERSISTENCE: 'persistence',\n DISPATCH: 'dispatch',\n} as const;\n\n// ---- \u5065\u5EB7\u5224\u5B9A\u72B6\u6001\uFF08DataBusHealthSummary['state']\uFF09----\nexport const HEALTH_STATE = {\n STOPPED: 'stopped',\n STARTING: 'starting',\n HEALTHY: 'healthy',\n RECOVERING: 'recovering',\n SUSPENDED: 'suspended',\n DEGRADED: 'degraded',\n} as const;\n\n// ---- WebSocket wire \u534F\u8BAE\u64CD\u4F5C\u7801 ----\nexport const WS_OP = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n PUBLISH: 'publish',\n PUBLISH_BATCH: 'publishBatch',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u5165\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_INPUT_TYPE = {\n INIT: 'INIT',\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n PUBLISH_BIN: 'PUBLISH_BIN',\n PING: 'PING',\n STOP: 'STOP',\n TOKEN_RESPONSE: 'TOKEN_RESPONSE',\n TOKEN_ERROR: 'TOKEN_ERROR',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u51FA\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_OUTPUT_TYPE = {\n STATUS: 'STATUS',\n MESSAGE: 'MESSAGE',\n MESSAGE_BIN: 'MESSAGE_BIN',\n ERROR: 'ERROR',\n TOKEN_REQUEST: 'TOKEN_REQUEST',\n} as const;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,18 @@
1
1
  import type { ClusterEnvironment } from './environment';
2
- import type { DataBusPublicationMetadata, WorkerControlAction, WorkerRecord, WorkerRoute, WorkerStatus } from './types';
2
+ import type { DataBusPublicationMetadata, LoadWeightingOptions, WorkerControlAction, WorkerRecord, WorkerRoute, WorkerStatus } from './types';
3
+ import { RELIABILITY_OPERATION } from '../utils/constants';
3
4
  /** Callbacks the cluster invokes to drive the transport and lifecycle. */
4
5
  export interface WorkerClusterHandlers {
5
6
  /** A SUBSCRIBE/UNSUBSCRIBE/PUBLISH control action was received for this worker. */
6
7
  onControl: (action: WorkerControlAction, topic: string, data?: unknown, messageId?: string, timestamp?: number) => void;
8
+ /** Optional batched variant of the PUBLISH action: invoked once when a
9
+ * CONTROL frame carries multiple publication items. When absent, the
10
+ * cluster falls back to per-item `onControl('PUBLISH', …)` calls. */
11
+ onPublishBatch?: (topic: string, items: ReadonlyArray<{
12
+ data: unknown;
13
+ messageId?: string;
14
+ timestamp?: number;
15
+ }>) => void;
7
16
  /** A fan-out publication event was received from another Worker.
8
17
  * `originTabId` is the tab that produced the original publication when the
9
18
  * cluster forwards one; it survives the BroadcastChannel hop so listeners
@@ -15,9 +24,9 @@ export interface WorkerClusterHandlers {
15
24
  onSuspend?: () => void;
16
25
  /** The cluster resumed (tab visible / pageshow). */
17
26
  onResume?: () => void;
18
- /** Bounded diagnostics for route confirmation and graceful migration. */
27
+ /** Bounded diagnostics for route confirmation, graceful migration, and stranded-handoff recovery. */
19
28
  onDiagnostic?: (event: {
20
- operation: 'route_ack' | 'route_migration';
29
+ operation: (typeof RELIABILITY_OPERATION.ROUTE_ACK | typeof RELIABILITY_OPERATION.ROUTE_MIGRATION | typeof RELIABILITY_OPERATION.ROUTE_MIGRATION_RECOVERY);
21
30
  topic: string;
22
31
  }) => void;
23
32
  }
@@ -44,6 +53,11 @@ export interface WorkerClusterOptions {
44
53
  /** Maximum entries kept in the publish route-owner cache (default 256).
45
54
  * When the cap is reached, the oldest (FIFO) entry is evicted. */
46
55
  routeOwnerCacheMax?: number;
56
+ /** Optional adaptive owner weighting. When set, this worker samples its own
57
+ * fan-out traffic and publishes it with every heartbeat so peers can steer
58
+ * NEW routes toward quieter workers; the weights are forwarded to the
59
+ * least-loaded selection. Absent (default) keeps pure topic-count routing. */
60
+ loadWeighting?: LoadWeightingOptions;
47
61
  }
48
62
  /** Read-only snapshot of the cluster state for diagnostics and tracing. */
49
63
  export interface WorkerClusterSnapshot {
@@ -98,6 +112,10 @@ export declare class WorkerClusterRuntime {
98
112
  private readonly routePrefix;
99
113
  private readonly subscriberPrefix;
100
114
  private readonly channelName;
115
+ /** Adaptive load weighting options; undefined keeps legacy topic-count routing. */
116
+ private readonly loadWeighting;
117
+ /** Rolling traffic accumulator folded into the worker record on writeRecord. */
118
+ private throughputWindow;
101
119
  private readonly subscribedTopics;
102
120
  private readonly assignedTopics;
103
121
  private readonly routeOwnerCache;
@@ -180,6 +198,9 @@ export declare class WorkerClusterRuntime {
180
198
  private resolvePublishTarget;
181
199
  /** Fan out a single batched item to the local onControl path. */
182
200
  private dispatchLocalPublish;
201
+ /** Fan out a publication batch to the local onControl path: one
202
+ * onPublishBatch call when the owner supports it, per-item otherwise. */
203
+ private dispatchLocalPublishBatch;
183
204
  /** True when `route` exists and its owner worker is among `workers`.
184
205
  * Shared by subscribe (skip re-assignment) and publish (route to owner).
185
206
  * Intentionally returns a plain boolean (not a type guard) so the caller
@@ -189,6 +210,13 @@ export declare class WorkerClusterRuntime {
189
210
  * `originTabId` (when set) is propagated across the BroadcastChannel hop so
190
211
  * listeners can attribute the event to its source tab even after fan-out. */
191
212
  broadcastEvent(eventType: string, payload: unknown, originTabId?: string): void;
213
+ /** Count one fan-out unit toward the adaptive load sample. No-op unless
214
+ * adaptive weighting is configured. */
215
+ private recordTraffic;
216
+ /** Convert the accumulated window into a publishable throughput sample and
217
+ * reset the accumulator. Returns undefined until a full window has elapsed
218
+ * so the first write does not emit a zero-width sample. */
219
+ private sampleThroughput;
192
220
  isAssigned(topic: string): boolean;
193
221
  /** True if this worker is among the active set (eligible to own topics). */
194
222
  isActiveWorker(): boolean;
@@ -232,8 +260,16 @@ export declare class WorkerClusterRuntime {
232
260
  private handleRouteReleasedMessage;
233
261
  /** A ROUTE_RELEASED is stale (and must be dropped) unless the route still
234
262
  * points to us, the release comes from the recorded previous owner, and
235
- * the release generation is at least as new as ours. */
263
+ * the release generation is at least as new as ours. A replayed ACK from an
264
+ * earlier handoff round (e.g. an a↔b ping-pong) carries an older generation
265
+ * and must not confirm the current round. */
236
266
  private isStaleRouteRelease;
267
+ /** True when an unconfirmed handoff route has been stuck longer than a
268
+ * worker TTL. The ACK for a live handoff is posted synchronously with the
269
+ * route write, so anything older than the TTL with a dead previous owner
270
+ * will never complete — while a fresh unconfirmed route may simply be
271
+ * waiting out its confirmation flush and must be left alone. */
272
+ private isStaleHandoff;
237
273
  /** Full reconciliation cycle: workers, subscriptions, and assigned topics. */
238
274
  private reconcile;
239
275
  /** Prune stale workers/subscribers/routes and refresh role. Returns the live worker list.
@@ -1 +1 @@
1
- {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import type { WorkerClusterOptions, WorkerClusterSnapshot } from './cluster';
2
2
  import type { DataBusErrorHandler, DataBusMessageHandler, DataBusPublishOptions, DataBusStatusHandler, DataBusTransport, WorkerStatus } from './types';
3
- import type { DataBusTraceOptions } from './trace';
3
+ import type { DataBusMetricsSnapshot, DataBusTraceOptions } from './trace';
4
4
  import type { DataBusReplayPersistence } from './replay-persistence';
5
+ import type { DataBusDedupOptions, DataBusDedupStats } from './dedup-manager';
6
+ import { FAILURE_SOURCE, HEALTH_STATE, PRUNE_STRATEGY } from '../utils/constants';
5
7
  /** Constructor options for {@link CrossTabDataBus}. Extends WorkerClusterOptions
6
8
  * (cluster coordination config) with the transport, initial connection config,
7
9
  * and trace options. */
@@ -11,15 +13,21 @@ import type { DataBusReplayPersistence } from './replay-persistence';
11
13
  * Buffers live in memory by default; an optional persistence backend can make
12
14
  * them durable. */
13
15
  export interface DataBusReplayOptions<TData = unknown> {
14
- /** Maximum buffered publications per topic. Oldest entries are evicted
15
- * first. Default 100. */
16
+ /** Maximum buffered publications per topic under 'count'/'both'. With 'age',
17
+ * timestamped history is bounded by `retentionMs` and timestamp-less legacy
18
+ * entries are capped by this value. Oldest entries are evicted first.
19
+ * Default 100. */
16
20
  maxPerTopic?: number;
17
21
  /** Optional durable history backend. Defaults to in-memory only. */
18
22
  persistence?: DataBusReplayPersistence<TData>;
19
23
  /** Optional producer-timestamp retention window in milliseconds. */
20
24
  retentionMs?: number;
21
- /** History trimming policy. Defaults to both when both limits are configured. */
22
- pruneStrategy?: 'count' | 'age' | 'both';
25
+ /** History trimming policy: 'count' (default) caps each topic at
26
+ * `maxPerTopic`, 'age' prunes by `retentionMs`, and 'both' applies both.
27
+ * With 'age', timestamped entries are bounded by the retention window and
28
+ * timestamp-less legacy entries are capped by `maxPerTopic`. An 'age'
29
+ * strategy without `retentionMs` falls back to the count cap. */
30
+ pruneStrategy?: (typeof PRUNE_STRATEGY)[keyof typeof PRUNE_STRATEGY];
23
31
  /** Optional periodic sweep interval for durable retention cleanup. */
24
32
  retentionSweepMs?: number;
25
33
  /** Optional bounded retry policy for transient persistence failures. */
@@ -31,27 +39,7 @@ export interface DataBusPersistenceRetryOptions {
31
39
  /** Initial delay between attempts. Default 50ms. */
32
40
  backoffMs?: number;
33
41
  }
34
- /** Opt-in bounded duplicate suppression for publications carrying `messageId`. */
35
- export interface DataBusDedupOptions {
36
- maxEntries?: number;
37
- ttlMs?: number;
38
- /** Optional periodic sweep interval for quiet-topic expiry. */
39
- sweepMs?: number;
40
- /** Injectable epoch clock for deterministic tests and non-wall-clock hosts. */
41
- now?: () => number;
42
- /** Optional adaptive TTL bounds; enabled only when both are provided. */
43
- adaptiveTtl?: {
44
- minMs: number;
45
- maxMs: number;
46
- };
47
- }
48
- export interface DataBusDedupStats {
49
- enabled: boolean;
50
- tracked: number;
51
- suppressed: number;
52
- accepted: number;
53
- ttlMs?: number;
54
- }
42
+ export type { DataBusDedupOptions, DataBusDedupStats };
55
43
  export interface DataBusDiagnostics {
56
44
  sdkVersion: string;
57
45
  status: WorkerStatus;
@@ -72,7 +60,9 @@ export interface DataBusDiagnostics {
72
60
  enabled: boolean;
73
61
  topics: number;
74
62
  messages: number;
63
+ bytes: number;
75
64
  };
65
+ persistence: DataBusPersistenceHealth;
76
66
  protocol: {
77
67
  version: number;
78
68
  unknownMessages: number;
@@ -82,8 +72,64 @@ export interface DataBusDiagnostics {
82
72
  transport: {
83
73
  name: string;
84
74
  backend: string | null;
75
+ status: WorkerStatus;
76
+ suspended: boolean;
85
77
  };
86
78
  cluster: WorkerClusterSnapshot;
79
+ /** Current trace metrics window counters, or null when metrics are inactive. */
80
+ metrics: DataBusMetricsSnapshot | null;
81
+ /** Trace sink delivery mode and queued-event depth (asyncSink back-pressure). */
82
+ trace: {
83
+ asyncSink: boolean;
84
+ pendingEvents: number;
85
+ };
86
+ }
87
+ /** Where a retained failure originated, as surfaced by {@link DataBusHealthSummary}. */
88
+ export type DataBusFailureSource = (typeof FAILURE_SOURCE)[keyof typeof FAILURE_SOURCE];
89
+ export interface DataBusLastFailure {
90
+ source: DataBusFailureSource;
91
+ message: string;
92
+ at: number;
93
+ }
94
+ /** Bounded failure counters for the optional replay persistence backend. */
95
+ export interface DataBusPersistenceHealth {
96
+ /** Total persistence failures reported since the last explicit start(). */
97
+ failures: number;
98
+ lastFailureAt: number | null;
99
+ lastErrorMessage: string | null;
100
+ }
101
+ /** Compact single-object health verdict for dashboards and readiness probes.
102
+ * Unlike {@link DataBusDiagnostics} this answers one question first — is the
103
+ * bus usable right now — then attaches the failure and recovery context that
104
+ * explains the verdict. */
105
+ export interface DataBusHealthSummary {
106
+ /** True only while the bus is started, not suspended, and the transport is ready. */
107
+ healthy: boolean;
108
+ /** Lifecycle-derived verdict: 'stopped' | 'starting' | 'healthy' | 'recovering' | 'suspended' | 'degraded'.
109
+ * 'degraded' means automatic recovery is exhausted and the transport is still down — a manual
110
+ * start() (or resume) is required. */
111
+ state: (typeof HEALTH_STATE)[keyof typeof HEALTH_STATE];
112
+ status: WorkerStatus;
113
+ sdkVersion: string;
114
+ started: boolean;
115
+ suspended: boolean;
116
+ transport: {
117
+ name: string;
118
+ backend: string | null;
119
+ ready: boolean;
120
+ status: WorkerStatus;
121
+ };
122
+ recovery: ReturnType<CrossTabDataBus['getRecoveryStats']>;
123
+ /** Most recent failure of any source since the last explicit start(). */
124
+ lastFailure: DataBusLastFailure | null;
125
+ persistence: DataBusPersistenceHealth;
126
+ /** Current trace metrics window, or null when trace metrics are inactive. */
127
+ metrics: DataBusMetricsSnapshot | null;
128
+ /** Trace sink delivery mode and queued-event depth (asyncSink back-pressure). */
129
+ trace: {
130
+ asyncSink: boolean;
131
+ pendingEvents: number;
132
+ };
87
133
  }
88
134
  export interface CrossTabDataBusOptions<TConfig, TData> extends Omit<WorkerClusterOptions, 'handlers'> {
89
135
  transport: DataBusTransport<TConfig, TData>;
@@ -115,37 +161,12 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
115
161
  private readonly transportSubscribedTopics;
116
162
  private readonly statusHandlers;
117
163
  private readonly errorHandlers;
118
- private readonly replayBuffers;
119
- private readonly replayMaxPerTopic;
120
- private readonly replayPersistence;
121
- private readonly replayRetentionMs;
122
- private readonly replayPruneStrategy;
123
- private readonly replayRetentionSweepMs;
124
- private readonly persistenceRetryMaxAttempts;
125
- private readonly persistenceRetryBackoffMs;
126
- private persistenceRetryGeneration;
127
- private pendingReplayPersistence;
128
- private replayPersistenceFlushScheduled;
129
- private readonly replayHydration;
130
- private replayRetentionCleanup;
131
- private replayRetentionCutoff;
132
- private replayRetentionTimer;
164
+ private readonly replayManager;
133
165
  private readonly initialConfig;
134
166
  private readonly hasInitialConfig;
135
167
  private readonly trace;
136
- private readonly dedupMaxEntries;
137
- private readonly dedupTtlMs;
138
- private readonly dedupAdaptiveBounds;
139
- private dedupWindowStartedAt;
140
- private dedupWindowAccepted;
141
- private readonly dedupAdaptiveWindowMs;
142
- private readonly dedupSweepMs;
143
- private dedupSweepTimer;
144
- private readonly dedupEnabled;
168
+ private readonly dedupManager;
145
169
  private readonly now;
146
- private readonly seenMessageIds;
147
- private dedupSuppressed;
148
- private dedupAccepted;
149
170
  private activeConfig;
150
171
  private status;
151
172
  private started;
@@ -153,7 +174,17 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
153
174
  private transportReady;
154
175
  private lastError;
155
176
  private lastErrorAt;
177
+ private lastFailure;
178
+ private persistenceFailureCount;
179
+ private persistenceLastFailureAt;
180
+ private persistenceLastErrorMessage;
156
181
  private startPromise;
182
+ private stopPromise;
183
+ private queuedStart;
184
+ private queuedStartReady;
185
+ private queuedStartReadyToken;
186
+ private queuedStartToken;
187
+ private canceledQueuedStartToken;
157
188
  private lastRecoveryAt;
158
189
  private recoveryAttempt;
159
190
  private recoveryExhausted;
@@ -166,6 +197,7 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
166
197
  private lastSuccessAt;
167
198
  private suspended;
168
199
  private pendingStop;
200
+ private lifecycleEpoch;
169
201
  private readonly recoveryCooldownMs;
170
202
  private readonly recoveryMaxAttempts;
171
203
  constructor(options: CrossTabDataBusOptions<TConfig, TData>);
@@ -173,11 +205,20 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
173
205
  * Start the DataBus with the given transport config.
174
206
  *
175
207
  * The first call starts the cluster and opens the transport. Concurrent calls
176
- * during an in-flight start return the same promise. Once the operation
177
- * settles (success or failure) the promise gate is cleared so a subsequent
178
- * start() or resumeTransport() can open a fresh lifecycle.
208
+ * during an in-flight open return the same promise. A call received while an
209
+ * explicit stop() is settling queues one fresh start after cleanup; a later
210
+ * stop() before that queued start runs cancels it, so the latest lifecycle
211
+ * intent wins. Once an operation settles (success or failure) its promise
212
+ * gate is cleared so a subsequent start() or resumeTransport() can open a
213
+ * fresh lifecycle.
179
214
  */
180
215
  start(config: TConfig): Promise<void>;
216
+ /** Return a cancellation-aware readiness view of the current queued start. */
217
+ private getQueuedStartReady;
218
+ /** Queue exactly one fresh start after an in-flight explicit stop settles. */
219
+ private queueStartAfterStop;
220
+ /** Reset failure and recovery diagnostics for a new explicit start session. */
221
+ private resetFailureState;
181
222
  /**
182
223
  * Open the transport, chained after `before` to ensure lifecycle ordering.
183
224
  * When `stopClusterOnFailure` is true (initial start), a transport failure
@@ -187,13 +228,17 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
187
228
  /**
188
229
  * Await the DataBus to be fully started (lazy init when using initialConfig).
189
230
  * Returns a rejected promise when the transport has failed and no start is in
190
- * flight — the caller can retry by calling start() or ready() again.
231
+ * flight — the caller can retry by calling start() or ready() again. While an
232
+ * explicit stop() is settling, this rejects unless a restart is queued behind
233
+ * it; false readiness during teardown is never reported.
191
234
  */
192
235
  ready(): Promise<void>;
193
236
  /**
194
237
  * Register a handler for `topic`. The handler fires on every publication
195
238
  * delivered to this tab, regardless of which tab published it. Returns an
196
- * unsubscribe function for convenience.
239
+ * unsubscribe function for convenience. During an explicit stop() the
240
+ * registration is rejected through onError and a no-op cleanup is returned,
241
+ * so a late subscriber cannot leak into a future restart.
197
242
  */
198
243
  subscribe(topic: string, handler: DataBusMessageHandler<TData>, options?: {
199
244
  replay?: boolean | number;
@@ -247,55 +292,60 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
247
292
  generation: number;
248
293
  lastSuccessAt: number | null;
249
294
  };
295
+ /** Bounded failure counters for the replay persistence backend. */
296
+ getPersistenceStats(): DataBusPersistenceHealth;
297
+ /** Compact health verdict for dashboards, readiness probes, and support
298
+ * bundles. Answers "is the bus usable right now" first, then attaches the
299
+ * unified failure ledger and recovery context that explains the verdict. */
300
+ getHealthSummary(): DataBusHealthSummary;
250
301
  /** Snapshot of the cluster state (workers, routes, assignments).
251
302
  * For diagnostics only — the returned object is a shallow copy but
252
303
  * nested arrays are snapshots at call time. */
253
304
  getClusterSnapshot(): WorkerClusterSnapshot;
254
305
  /** Return a single health snapshot combining lifecycle, recovery, dedup, replay, and cluster state. */
255
306
  getDiagnostics(): DataBusDiagnostics;
307
+ /** Synchronous snapshot of the current trace metrics window (throughput,
308
+ * dispatch latency, dedup outcomes), without flushing or resetting it.
309
+ * Returns null when trace metrics are inactive (disabled or events-only). */
310
+ getMetrics(): DataBusMetricsSnapshot | null;
256
311
  /**
257
312
  * Gracefully stop the DataBus: unsubscribe all topics, stop the cluster,
258
- * and close the transport. Idempotent.
313
+ * and close the transport. Concurrent and repeated calls share the in-flight
314
+ * stop promise. A start() received while stopping runs after this completes,
315
+ * unless another stop() arrives first and cancels that queued restart.
259
316
  */
260
317
  stop(): Promise<void>;
318
+ private performStop;
261
319
  /**
262
320
  * Incoming message from the transport.
263
321
  * Records metrics, checks ownership via the cluster, broadcasts to other tabs,
264
322
  * and dispatches locally.
265
323
  */
266
324
  private handleTransportMessage;
267
- private isDuplicate;
325
+ /** Start enqueuing the dedup expiry sweep (delegated to {@link DedupManager}). */
268
326
  private startDedupSweep;
327
+ /** Stop enqueuing the dedup expiry sweep. */
269
328
  private stopDedupSweep;
270
- private pruneExpiredDedup;
271
- private currentDedupTtl;
272
329
  /** Deliver a message to every local handler registered for its topic,
273
330
  * plus every handler registered with a wildcard subscription that matches
274
331
  * (e.g. a handler subscribed to "chat.*" receives "chat.room.1"). */
275
332
  private dispatch;
276
- /** Append a dispatched publication to the topic's replay ring buffer.
277
- * No-op when replay is disabled. */
278
- private recordReplay;
279
- private scheduleReplayPersistenceFlush;
280
- private hydrateReplay;
281
- private scheduleReplayRetentionCleanup;
282
- private startReplayRetentionSweep;
283
- private stopReplayRetentionSweep;
284
- private withPersistenceRetry;
285
- /** Deliver buffered history to a newly-registered handler. For an exact
286
- * topic this is that topic's ring; for a wildcard subscription every
287
- * buffered topic matching the pattern contributes (in buffer insertion
288
- * order). Replay deliveries are marked `replayed: true` and are not
289
- * counted into trace metrics. */
290
- private deliverReplay;
291
333
  /**
292
334
  * Propagate a status change to the cluster, trace, and all registered
293
335
  * status handlers. On reconnect, re-subscribe any topics assigned to us.
294
336
  */
295
337
  private updateStatus;
296
338
  private reportError;
339
+ /** Report a persistence failure to the trace and the unified failure ledger,
340
+ * unless it is a {@link PersistenceRetryCancelledError} cancellation from a
341
+ * lifecycle transition (teardown should stay quiet). */
297
342
  private reportPersistenceError;
298
343
  private traceSubscription;
344
+ /** Emit the coordination trace snapshot from the current cluster state.
345
+ * Called after a transport opens (start and recovery), when the role and
346
+ * route picture has settled — the synchronous pre-open snapshot would see no
347
+ * routes because their writes are still coalesced in the batch writer. */
348
+ private emitCoordinationTrace;
299
349
  /** Ask the transport to subscribe to a topic (idempotent). */
300
350
  private subscribeTransport;
301
351
  private unsubscribeTransport;
@@ -333,6 +383,13 @@ export declare class CrossTabDataBus<TConfig = unknown, TData = unknown> {
333
383
  * during startup are not lost.
334
384
  */
335
385
  private runTransport;
386
+ /**
387
+ * Publications started after teardown begins cannot reach any transport.
388
+ * Surface that as a normal asynchronous API failure instead of letting
389
+ * runTransport() return silently. Empty publishBatch() calls remain a no-op
390
+ * and are filtered by the caller before this check.
391
+ */
392
+ private rejectPublishDuringStop;
336
393
  /**
337
394
  * Ensure the DataBus is started, throwing if no initialConfig was provided.
338
395
  * Called automatically by subscribe/publish/ready when autoStart is true.