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.
@@ -1261,7 +1261,7 @@ var PersistenceRetryCancelledError = class extends Error {
1261
1261
  this.name = "PersistenceRetryCancelledError";
1262
1262
  }
1263
1263
  };
1264
- var CrossTabDataBus = class _CrossTabDataBus {
1264
+ var CrossTabDataBus = class {
1265
1265
  transport;
1266
1266
  cluster;
1267
1267
  // Map of topic → set of local subscribers.
@@ -1313,6 +1313,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
1313
1313
  // Timestamp of the last automatic transport recovery attempt.
1314
1314
  // Used to avoid a tight retry loop when the transport fails repeatedly.
1315
1315
  lastRecoveryAt = 0;
1316
+ // Monotonic attempt number within one runtime recovery sequence; reset once
1317
+ // a transport reopen succeeds so traces can correlate repeated failures.
1318
+ recoveryAttempt = 0;
1316
1319
  // True while the tab is hidden so an in-flight transport start does not mark
1317
1320
  // the transport ready after suspendTransport() has stopped it.
1318
1321
  suspended = false;
@@ -1322,7 +1325,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
1322
1325
  // stop to settle.
1323
1326
  pendingStop = null;
1324
1327
  // Minimum interval in ms between automatic recovery attempts.
1325
- static RECOVERY_COOLDOWN_MS = 1e3;
1328
+ recoveryCooldownMs;
1326
1329
  constructor(options) {
1327
1330
  const replay = options.replay;
1328
1331
  if (replay) {
@@ -1352,7 +1355,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
1352
1355
  if (!Number.isFinite(this.persistenceRetryBackoffMs) || this.persistenceRetryBackoffMs < 0) {
1353
1356
  throw new TypeError("replay.persistenceRetry.backoffMs must be a non-negative finite number.");
1354
1357
  }
1355
- const { autoStart, initialConfig, trace, transport, dedup, ...clusterOptions } = options;
1358
+ const { autoStart, initialConfig, trace, transport, dedup, recovery, ...clusterOptions } = options;
1359
+ this.recoveryCooldownMs = recovery?.cooldownMs ?? 1e3;
1360
+ if (!Number.isFinite(this.recoveryCooldownMs) || this.recoveryCooldownMs <= 0) {
1361
+ throw new TypeError("recovery.cooldownMs must be a positive finite number.");
1362
+ }
1356
1363
  this.now = dedup?.now ?? Date.now;
1357
1364
  this.replayHydration = this.hydrateReplay();
1358
1365
  this.transport = transport;
@@ -1908,14 +1915,15 @@ var CrossTabDataBus = class _CrossTabDataBus {
1908
1915
  }
1909
1916
  if (status === "error" && this.started && !this.stopping) {
1910
1917
  const now = this.now();
1911
- if (now - this.lastRecoveryAt >= _CrossTabDataBus.RECOVERY_COOLDOWN_MS) {
1918
+ if (now - this.lastRecoveryAt >= this.recoveryCooldownMs) {
1912
1919
  this.lastRecoveryAt = now;
1913
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "scheduled" });
1920
+ const attempt = ++this.recoveryAttempt;
1921
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt, outcome: "scheduled" });
1914
1922
  setTimeout(() => {
1915
1923
  if (this.stopping || !this.started || this.suspended) return;
1916
1924
  if (this.status !== "error") return;
1917
- void this.reopenTransport();
1918
- }, _CrossTabDataBus.RECOVERY_COOLDOWN_MS);
1925
+ void this.reopenTransport(attempt);
1926
+ }, this.recoveryCooldownMs);
1919
1927
  }
1920
1928
  }
1921
1929
  this.invokeHandlers(this.statusHandlers, (handler) => handler(status));
@@ -2005,10 +2013,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
2005
2013
  * its rejection so the reopen is not blocked. Returns the opening promise so
2006
2014
  * callers can queue operations behind it.
2007
2015
  */
2008
- reopenTransport() {
2016
+ reopenTransport(recoveryAttempt) {
2009
2017
  if (this.stopping || this.activeConfig === void 0) return Promise.resolve();
2010
2018
  if (this.startPromise && this.startPromise !== this.pendingStop) return this.startPromise;
2011
2019
  const config = this.activeConfig;
2020
+ const traceAttempt = recoveryAttempt ?? (this.recoveryAttempt > 0 ? this.recoveryAttempt : void 0);
2012
2021
  this.started = true;
2013
2022
  this.suspended = false;
2014
2023
  this.updateStatus("connecting");
@@ -2017,11 +2026,16 @@ var CrossTabDataBus = class _CrossTabDataBus {
2017
2026
  this.startPromise = opening;
2018
2027
  void opening.then(
2019
2028
  () => {
2020
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "succeeded" });
2029
+ if (traceAttempt !== void 0) {
2030
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: traceAttempt, outcome: "succeeded" });
2031
+ this.recoveryAttempt = 0;
2032
+ }
2021
2033
  if (this.startPromise === opening) this.startPromise = null;
2022
2034
  },
2023
2035
  () => {
2024
- this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1, outcome: "failed" });
2036
+ if (traceAttempt !== void 0) {
2037
+ this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: traceAttempt, outcome: "failed" });
2038
+ }
2025
2039
  }
2026
2040
  );
2027
2041
  void opening.catch(() => void 0);