cross-tab-worker-databus 0.20.88 → 0.20.89

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.
@@ -1659,8 +1659,9 @@ var DataBusTraceReporter = class {
1659
1659
  /** Start the periodic metrics flush interval. No-op when mode is 'events'
1660
1660
  * (no metrics to emit), when disabled, or when already running. */
1661
1661
  start() {
1662
- if (!this.enabled || this.intervalHandle || this.mode === TRACE_MODE.EVENTS) return;
1662
+ if (!this.enabled) return;
1663
1663
  this.stopped = false;
1664
+ if (this.intervalHandle || this.mode === TRACE_MODE.EVENTS) return;
1664
1665
  this.intervalStartedAt = this.now();
1665
1666
  this.intervalHandle = setInterval(() => this.flush(), this.metricsIntervalMs);
1666
1667
  }
@@ -1673,6 +1674,7 @@ var DataBusTraceReporter = class {
1673
1674
  }
1674
1675
  stop() {
1675
1676
  this.stopped = true;
1677
+ this.pendingEvents = [];
1676
1678
  this.pause();
1677
1679
  }
1678
1680
  /** Synchronous sink state for diagnostics: whether delivery is async and how
@@ -1683,7 +1685,7 @@ var DataBusTraceReporter = class {
1683
1685
  }
1684
1686
  /** Record an instantaneous trace event (lifecycle, status, error, etc.). */
1685
1687
  event(event) {
1686
- if (!this.enabled || this.mode === TRACE_MODE.METRICS) return;
1688
+ if (!this.enabled || this.stopped || this.mode === TRACE_MODE.METRICS) return;
1687
1689
  this.emit({ ...event, timestamp: this.now() });
1688
1690
  }
1689
1691
  /** Synchronous snapshot of the current metrics window without resetting it.
@@ -1766,7 +1768,7 @@ var DataBusTraceReporter = class {
1766
1768
  * Extracted so the four record / flush methods share one guard expression
1767
1769
  * instead of repeating `!this.enabled || this.mode === 'events'` at each. */
1768
1770
  get metricsActive() {
1769
- return this.enabled && this.mode !== TRACE_MODE.EVENTS;
1771
+ return this.enabled && !this.stopped && this.mode !== TRACE_MODE.EVENTS;
1770
1772
  }
1771
1773
  /** Emit the accumulated metrics snapshot if the interval is active. */
1772
1774
  flush() {
@@ -2068,6 +2070,8 @@ var ReplayManager = class {
2068
2070
  * or stopped bus does not keep hammering the store) and stop the sweep. */
2069
2071
  suspend() {
2070
2072
  this.retryGeneration += 1;
2073
+ this.pendingReplayPersistence = [];
2074
+ this.retentionCutoff = null;
2071
2075
  this.stop();
2072
2076
  }
2073
2077
  /** Drop all in-memory buffers (used on full teardown). */
@@ -2166,19 +2170,20 @@ var ReplayManager = class {
2166
2170
  this.retentionCutoff = cutoff;
2167
2171
  }
2168
2172
  if (this.retentionCleanup) return;
2173
+ const generation = this.retryGeneration;
2169
2174
  this.retentionCleanup = (async () => {
2170
- while (this.retentionCutoff !== null) {
2175
+ while (this.retentionCutoff !== null && generation === this.retryGeneration) {
2171
2176
  const nextCutoff = this.retentionCutoff;
2172
2177
  this.retentionCutoff = null;
2173
2178
  try {
2174
2179
  await this.persistence.clearBefore(nextCutoff);
2175
2180
  } catch (error) {
2176
- this.onPersistenceError(error);
2181
+ if (generation === this.retryGeneration) this.onPersistenceError(error);
2177
2182
  }
2178
2183
  }
2179
2184
  })().finally(() => {
2180
2185
  this.retentionCleanup = null;
2181
- if (this.retentionCutoff !== null) {
2186
+ if (this.retentionCutoff !== null && generation === this.retryGeneration) {
2182
2187
  this.scheduleRetentionCleanup(this.retentionCutoff);
2183
2188
  }
2184
2189
  });
@@ -2195,7 +2200,9 @@ var ReplayManager = class {
2195
2200
  attempt += 1;
2196
2201
  try {
2197
2202
  if (generation !== this.retryGeneration) throw new PersistenceRetryCancelledError();
2198
- return await operation();
2203
+ const result = await operation();
2204
+ if (generation !== this.retryGeneration) throw new PersistenceRetryCancelledError();
2205
+ return result;
2199
2206
  } catch (error) {
2200
2207
  if (error instanceof PersistenceRetryCancelledError || generation !== this.retryGeneration) {
2201
2208
  throw new PersistenceRetryCancelledError();
@@ -2329,7 +2336,7 @@ var DedupManager = class {
2329
2336
  };
2330
2337
 
2331
2338
  // src/core/version.ts
2332
- var SDK_VERSION = true ? "0.20.88" : "";
2339
+ var SDK_VERSION = true ? "0.20.89" : "";
2333
2340
 
2334
2341
  // src/core/data-bus.ts
2335
2342
  var DEFAULT_REPLAY_MAX_PER_TOPIC = 100;
@@ -2564,8 +2571,8 @@ var CrossTabDataBus = class {
2564
2571
  this.suspended = false;
2565
2572
  this.activeConfig = config;
2566
2573
  this.resetFailureState();
2567
- this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.START });
2568
2574
  this.trace.start();
2575
+ this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.START });
2569
2576
  this.startDedupSweep();
2570
2577
  this.replayManager.start();
2571
2578
  this.updateStatus(WORKER_STATUS.CONNECTING);
@@ -2925,7 +2932,7 @@ var CrossTabDataBus = class {
2925
2932
  getHealthSummary() {
2926
2933
  const transport = this.transport;
2927
2934
  const transportDown = this.status !== WORKER_STATUS.CONNECTED;
2928
- const state = !this.started ? HEALTH_STATE.STOPPED : this.suspended ? HEALTH_STATE.SUSPENDED : transportDown ? this.recoveryExhausted ? HEALTH_STATE.DEGRADED : this.status === WORKER_STATUS.CONNECTING && this.recoveryAttempt === 0 ? HEALTH_STATE.STARTING : HEALTH_STATE.RECOVERING : HEALTH_STATE.HEALTHY;
2935
+ const state = !this.started || this.stopping ? HEALTH_STATE.STOPPED : this.suspended ? HEALTH_STATE.SUSPENDED : transportDown ? this.recoveryExhausted ? HEALTH_STATE.DEGRADED : this.status === WORKER_STATUS.CONNECTING && this.recoveryAttempt === 0 ? HEALTH_STATE.STARTING : HEALTH_STATE.RECOVERING : HEALTH_STATE.HEALTHY;
2929
2936
  return {
2930
2937
  healthy: state === HEALTH_STATE.HEALTHY,
2931
2938
  state,
@@ -2996,7 +3003,7 @@ var CrossTabDataBus = class {
2996
3003
  this.canceledQueuedStartToken = this.queuedStartToken;
2997
3004
  this.queuedStart = null;
2998
3005
  }
2999
- if (this.stopPromise) return this.stopPromise;
3006
+ if (this.stopPromise && this.stopping) return this.stopPromise;
3000
3007
  if (!this.started && !this.startPromise && !this.pendingStop && !this.transportReady) {
3001
3008
  return Promise.resolve();
3002
3009
  }
@@ -3240,8 +3247,8 @@ var CrossTabDataBus = class {
3240
3247
  * pageshow path and explicit start() must run this so an explicit resume
3241
3248
  * cannot leave trace metrics and periodic cleanup timers permanently off. */
3242
3249
  resumeSuspendedResources() {
3243
- this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.RESUME });
3244
3250
  this.trace.start();
3251
+ this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.RESUME });
3245
3252
  this.startDedupSweep();
3246
3253
  this.replayManager.start();
3247
3254
  }
@@ -3936,10 +3943,16 @@ var WebSocketTransport = class {
3936
3943
  * server cannot crash the message path. */
3937
3944
  async handleMessage(raw) {
3938
3945
  if (typeof Blob !== "undefined" && raw instanceof Blob) {
3946
+ const socket = this.socket;
3947
+ const handlers = this.handlers;
3939
3948
  try {
3940
- await this.handleMessage(await raw.arrayBuffer());
3949
+ const buffer = await raw.arrayBuffer();
3950
+ if (this.socket !== socket || this.handlers !== handlers || !this.socketActive) return;
3951
+ await this.handleMessage(buffer);
3941
3952
  } catch (error) {
3942
- this.handlers?.onError(error);
3953
+ if (this.socket === socket && this.handlers === handlers && this.socketActive) {
3954
+ this.handlers?.onError(error);
3955
+ }
3943
3956
  }
3944
3957
  return;
3945
3958
  }