cross-tab-worker-databus 0.20.16 → 0.20.18

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.
@@ -1236,7 +1236,7 @@ var PersistenceRetryCancelledError = class extends Error {
1236
1236
  this.name = "PersistenceRetryCancelledError";
1237
1237
  }
1238
1238
  };
1239
- var CrossTabDataBus = class _CrossTabDataBus {
1239
+ var CrossTabDataBus = class {
1240
1240
  transport;
1241
1241
  cluster;
1242
1242
  // Map of topic → set of local subscribers.
@@ -1288,6 +1288,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
1288
1288
  // Timestamp of the last automatic transport recovery attempt.
1289
1289
  // Used to avoid a tight retry loop when the transport fails repeatedly.
1290
1290
  lastRecoveryAt = 0;
1291
+ // Monotonic attempt number within one runtime recovery sequence; reset once
1292
+ // a transport reopen succeeds so traces can correlate repeated failures.
1293
+ recoveryAttempt = 0;
1291
1294
  // True while the tab is hidden so an in-flight transport start does not mark
1292
1295
  // the transport ready after suspendTransport() has stopped it.
1293
1296
  suspended = false;
@@ -1297,7 +1300,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
1297
1300
  // stop to settle.
1298
1301
  pendingStop = null;
1299
1302
  // Minimum interval in ms between automatic recovery attempts.
1300
- static RECOVERY_COOLDOWN_MS = 1e3;
1303
+ recoveryCooldownMs;
1301
1304
  constructor(options) {
1302
1305
  const replay = options.replay;
1303
1306
  if (replay) {
@@ -1327,7 +1330,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
1327
1330
  if (!Number.isFinite(this.persistenceRetryBackoffMs) || this.persistenceRetryBackoffMs < 0) {
1328
1331
  throw new TypeError("replay.persistenceRetry.backoffMs must be a non-negative finite number.");
1329
1332
  }
1330
- const { autoStart, initialConfig, trace, transport, dedup, ...clusterOptions } = options;
1333
+ const { autoStart, initialConfig, trace, transport, dedup, recovery, ...clusterOptions } = options;
1334
+ this.recoveryCooldownMs = recovery?.cooldownMs ?? 1e3;
1335
+ if (!Number.isFinite(this.recoveryCooldownMs) || this.recoveryCooldownMs <= 0) {
1336
+ throw new TypeError("recovery.cooldownMs must be a positive finite number.");
1337
+ }
1331
1338
  this.now = dedup?.now ?? Date.now;
1332
1339
  this.replayHydration = this.hydrateReplay();
1333
1340
  this.transport = transport;
@@ -1883,14 +1890,15 @@ var CrossTabDataBus = class _CrossTabDataBus {
1883
1890
  }
1884
1891
  if (status === "error" && this.started && !this.stopping) {
1885
1892
  const now = this.now();
1886
- if (now - this.lastRecoveryAt >= _CrossTabDataBus.RECOVERY_COOLDOWN_MS) {
1893
+ if (now - this.lastRecoveryAt >= this.recoveryCooldownMs) {
1887
1894
  this.lastRecoveryAt = now;
1888
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "scheduled" });
1895
+ const attempt = ++this.recoveryAttempt;
1896
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt, outcome: "scheduled" });
1889
1897
  setTimeout(() => {
1890
1898
  if (this.stopping || !this.started || this.suspended) return;
1891
1899
  if (this.status !== "error") return;
1892
- void this.reopenTransport();
1893
- }, _CrossTabDataBus.RECOVERY_COOLDOWN_MS);
1900
+ void this.reopenTransport(attempt);
1901
+ }, this.recoveryCooldownMs);
1894
1902
  }
1895
1903
  }
1896
1904
  this.invokeHandlers(this.statusHandlers, (handler) => handler(status));
@@ -1980,10 +1988,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
1980
1988
  * its rejection so the reopen is not blocked. Returns the opening promise so
1981
1989
  * callers can queue operations behind it.
1982
1990
  */
1983
- reopenTransport() {
1991
+ reopenTransport(recoveryAttempt) {
1984
1992
  if (this.stopping || this.activeConfig === void 0) return Promise.resolve();
1985
1993
  if (this.startPromise && this.startPromise !== this.pendingStop) return this.startPromise;
1986
1994
  const config = this.activeConfig;
1995
+ const traceAttempt = recoveryAttempt ?? (this.recoveryAttempt > 0 ? this.recoveryAttempt : void 0);
1987
1996
  this.started = true;
1988
1997
  this.suspended = false;
1989
1998
  this.updateStatus("connecting");
@@ -1992,11 +2001,16 @@ var CrossTabDataBus = class _CrossTabDataBus {
1992
2001
  this.startPromise = opening;
1993
2002
  void opening.then(
1994
2003
  () => {
1995
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "succeeded" });
2004
+ if (traceAttempt !== void 0) {
2005
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: traceAttempt, outcome: "succeeded" });
2006
+ this.recoveryAttempt = 0;
2007
+ }
1996
2008
  if (this.startPromise === opening) this.startPromise = null;
1997
2009
  },
1998
2010
  () => {
1999
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "failed" });
2011
+ if (traceAttempt !== void 0) {
2012
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: traceAttempt, outcome: "failed" });
2013
+ }
2000
2014
  }
2001
2015
  );
2002
2016
  void opening.catch(() => void 0);