cross-tab-worker-databus 0.11.0 → 0.20.7
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.
- package/CHANGELOG.md +216 -0
- package/dist/centrifuge.js +1 -1
- package/dist/centrifuge.shared.worker.js +4 -2
- package/dist/centrifuge.shared.worker.js.map +2 -2
- package/dist/centrifuge.worker.js +4 -2
- package/dist/centrifuge.worker.js.map +2 -2
- package/dist/{chunk-NX76TAV3.js → chunk-LPS4XOK4.js} +152 -20
- package/dist/{chunk-NX76TAV3.js.map → chunk-LPS4XOK4.js.map} +2 -2
- package/dist/cjs/centrifuge.cjs +151 -19
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/hooks.cjs +4 -1
- package/dist/cjs/hooks.cjs.map +2 -2
- package/dist/cjs/index.cjs +301 -68
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/cjs/vue.cjs +7 -1
- package/dist/cjs/vue.cjs.map +2 -2
- package/dist/core/data-bus.d.ts +32 -0
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/core/publication.d.ts.map +1 -1
- package/dist/core/replay-persistence.d.ts.map +1 -1
- package/dist/core/trace.d.ts +4 -1
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +4 -1
- package/dist/hooks.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +151 -50
- package/dist/index.js.map +2 -2
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +7 -1
- package/dist/vue.js.map +2 -2
- package/dist/websocket.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/api.md +10 -3
- package/docs/configuration.md +21 -1
- package/docs/release-checklist.md +22 -0
- package/docs/roadmap.md +136 -3
- package/docs/zh/README.md +1 -0
- package/docs/zh/api.md +10 -3
- package/docs/zh/configuration.md +21 -1
- package/docs/zh/release-checklist.md +22 -0
- package/docs/zh/roadmap.md +137 -2
- package/package.json +3 -1
package/dist/cjs/centrifuge.cjs
CHANGED
|
@@ -1068,7 +1068,7 @@ var DataBusTraceReporter = class {
|
|
|
1068
1068
|
latencySumMs = 0;
|
|
1069
1069
|
dedupAccepted = 0;
|
|
1070
1070
|
dedupSuppressed = 0;
|
|
1071
|
-
constructor(options, now = Date.now) {
|
|
1071
|
+
constructor(options, now = options?.now ?? Date.now) {
|
|
1072
1072
|
this.enabled = options?.enabled ?? false;
|
|
1073
1073
|
this.mode = options?.mode ?? "all";
|
|
1074
1074
|
this.metricsIntervalMs = normalizeInterval(options?.metricsIntervalMs);
|
|
@@ -1230,6 +1230,12 @@ function roundMs(value) {
|
|
|
1230
1230
|
// src/core/data-bus.ts
|
|
1231
1231
|
var PUBLICATION_EVENT = "DATABUS_PUBLICATION";
|
|
1232
1232
|
var DEFAULT_REPLAY_MAX_PER_TOPIC = 100;
|
|
1233
|
+
var PersistenceRetryCancelledError = class extends Error {
|
|
1234
|
+
constructor() {
|
|
1235
|
+
super("Persistence retry cancelled by lifecycle transition.");
|
|
1236
|
+
this.name = "PersistenceRetryCancelledError";
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1233
1239
|
var CrossTabDataBus = class _CrossTabDataBus {
|
|
1234
1240
|
transport;
|
|
1235
1241
|
cluster;
|
|
@@ -1246,13 +1252,25 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1246
1252
|
replayMaxPerTopic;
|
|
1247
1253
|
replayPersistence;
|
|
1248
1254
|
replayRetentionMs;
|
|
1255
|
+
replayRetentionSweepMs;
|
|
1256
|
+
persistenceRetryMaxAttempts;
|
|
1257
|
+
persistenceRetryBackoffMs;
|
|
1258
|
+
persistenceRetryGeneration = 0;
|
|
1249
1259
|
replayHydration;
|
|
1260
|
+
// Retention cleanup is coalesced so a burst of publications does not issue
|
|
1261
|
+
// one IndexedDB read/write transaction per message. The newest cutoff wins.
|
|
1262
|
+
replayRetentionCleanup = null;
|
|
1263
|
+
replayRetentionCutoff = null;
|
|
1264
|
+
replayRetentionTimer = null;
|
|
1250
1265
|
initialConfig;
|
|
1251
1266
|
hasInitialConfig;
|
|
1252
1267
|
trace;
|
|
1253
1268
|
dedupMaxEntries;
|
|
1254
1269
|
dedupTtlMs;
|
|
1270
|
+
dedupSweepMs;
|
|
1271
|
+
dedupSweepTimer = null;
|
|
1255
1272
|
dedupEnabled;
|
|
1273
|
+
now;
|
|
1256
1274
|
seenMessageIds = /* @__PURE__ */ new Map();
|
|
1257
1275
|
dedupSuppressed = 0;
|
|
1258
1276
|
dedupAccepted = 0;
|
|
@@ -1297,14 +1315,28 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1297
1315
|
if (this.replayRetentionMs !== void 0 && (!Number.isFinite(this.replayRetentionMs) || this.replayRetentionMs <= 0)) {
|
|
1298
1316
|
throw new TypeError("replay.retentionMs must be a positive finite number.");
|
|
1299
1317
|
}
|
|
1300
|
-
this.
|
|
1318
|
+
this.replayRetentionSweepMs = replay?.retentionSweepMs;
|
|
1319
|
+
if (this.replayRetentionSweepMs !== void 0 && (!Number.isFinite(this.replayRetentionSweepMs) || this.replayRetentionSweepMs <= 0)) {
|
|
1320
|
+
throw new TypeError("replay.retentionSweepMs must be a positive finite number.");
|
|
1321
|
+
}
|
|
1322
|
+
this.persistenceRetryMaxAttempts = replay?.persistenceRetry?.maxAttempts ?? 1;
|
|
1323
|
+
this.persistenceRetryBackoffMs = replay?.persistenceRetry?.backoffMs ?? 50;
|
|
1324
|
+
if (!Number.isSafeInteger(this.persistenceRetryMaxAttempts) || this.persistenceRetryMaxAttempts <= 0) {
|
|
1325
|
+
throw new TypeError("replay.persistenceRetry.maxAttempts must be a positive safe integer.");
|
|
1326
|
+
}
|
|
1327
|
+
if (!Number.isFinite(this.persistenceRetryBackoffMs) || this.persistenceRetryBackoffMs < 0) {
|
|
1328
|
+
throw new TypeError("replay.persistenceRetry.backoffMs must be a non-negative finite number.");
|
|
1329
|
+
}
|
|
1301
1330
|
const { autoStart, initialConfig, trace, transport, dedup, ...clusterOptions } = options;
|
|
1331
|
+
this.now = dedup?.now ?? Date.now;
|
|
1332
|
+
this.replayHydration = this.hydrateReplay();
|
|
1302
1333
|
this.transport = transport;
|
|
1303
1334
|
this.initialConfig = initialConfig;
|
|
1304
1335
|
this.hasInitialConfig = "initialConfig" in options;
|
|
1305
1336
|
this.trace = new DataBusTraceReporter(trace);
|
|
1306
1337
|
this.dedupMaxEntries = dedup?.maxEntries ?? 1e3;
|
|
1307
1338
|
this.dedupTtlMs = dedup?.ttlMs ?? 6e4;
|
|
1339
|
+
this.dedupSweepMs = dedup?.sweepMs;
|
|
1308
1340
|
this.dedupEnabled = dedup !== void 0;
|
|
1309
1341
|
if (!Number.isSafeInteger(this.dedupMaxEntries) || this.dedupMaxEntries <= 0) {
|
|
1310
1342
|
throw new TypeError("dedup.maxEntries must be a positive safe integer.");
|
|
@@ -1312,6 +1344,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1312
1344
|
if (!Number.isFinite(this.dedupTtlMs) || this.dedupTtlMs <= 0) {
|
|
1313
1345
|
throw new TypeError("dedup.ttlMs must be a positive finite number.");
|
|
1314
1346
|
}
|
|
1347
|
+
if (this.dedupSweepMs !== void 0 && (!Number.isFinite(this.dedupSweepMs) || this.dedupSweepMs <= 0)) {
|
|
1348
|
+
throw new TypeError("dedup.sweepMs must be a positive finite number.");
|
|
1349
|
+
}
|
|
1315
1350
|
this.cluster = new WorkerClusterRuntime({
|
|
1316
1351
|
...clusterOptions,
|
|
1317
1352
|
handlers: {
|
|
@@ -1352,11 +1387,16 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1352
1387
|
onSuspend: () => {
|
|
1353
1388
|
if (!this.stopping) this.trace.event({ type: "lifecycle", action: "suspend" });
|
|
1354
1389
|
this.trace.pause();
|
|
1390
|
+
this.persistenceRetryGeneration += 1;
|
|
1391
|
+
this.stopDedupSweep();
|
|
1392
|
+
this.stopReplayRetentionSweep();
|
|
1355
1393
|
this.suspendTransport();
|
|
1356
1394
|
},
|
|
1357
1395
|
onResume: () => {
|
|
1358
1396
|
this.trace.event({ type: "lifecycle", action: "resume" });
|
|
1359
1397
|
this.trace.start();
|
|
1398
|
+
this.startDedupSweep();
|
|
1399
|
+
this.startReplayRetentionSweep();
|
|
1360
1400
|
this.resumeTransport();
|
|
1361
1401
|
},
|
|
1362
1402
|
onDiagnostic: (event) => {
|
|
@@ -1384,6 +1424,8 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1384
1424
|
this.lastError = null;
|
|
1385
1425
|
this.trace.event({ type: "lifecycle", action: "start" });
|
|
1386
1426
|
this.trace.start();
|
|
1427
|
+
this.startDedupSweep();
|
|
1428
|
+
this.startReplayRetentionSweep();
|
|
1387
1429
|
this.updateStatus("connecting");
|
|
1388
1430
|
this.cluster.start();
|
|
1389
1431
|
const opening = this.openTransport(config, this.pendingStop ?? Promise.resolve(), true);
|
|
@@ -1508,7 +1550,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1508
1550
|
this.topicHandlers.delete(topic);
|
|
1509
1551
|
this.replayBuffers?.delete(topic);
|
|
1510
1552
|
if (this.replayPersistence?.clearTopic) {
|
|
1511
|
-
void this.replayPersistence.clearTopic(topic).catch((error) => this.
|
|
1553
|
+
void this.withPersistenceRetry("clearTopic", () => this.replayPersistence.clearTopic(topic)).catch((error) => this.reportPersistenceError(error));
|
|
1512
1554
|
}
|
|
1513
1555
|
this.cluster.unsubscribe(topic);
|
|
1514
1556
|
}
|
|
@@ -1517,9 +1559,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1517
1559
|
this.replayBuffers?.clear();
|
|
1518
1560
|
if (this.replayPersistence?.clear) {
|
|
1519
1561
|
try {
|
|
1520
|
-
await this.replayPersistence.clear();
|
|
1562
|
+
await this.withPersistenceRetry("clear", () => this.replayPersistence.clear());
|
|
1521
1563
|
} catch (error) {
|
|
1522
|
-
this.
|
|
1564
|
+
this.reportPersistenceError(error);
|
|
1523
1565
|
throw error;
|
|
1524
1566
|
}
|
|
1525
1567
|
}
|
|
@@ -1529,9 +1571,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1529
1571
|
this.replayBuffers?.delete(topic);
|
|
1530
1572
|
if (this.replayPersistence?.clearTopic) {
|
|
1531
1573
|
try {
|
|
1532
|
-
await this.replayPersistence.clearTopic(topic);
|
|
1574
|
+
await this.withPersistenceRetry("clearTopic", () => this.replayPersistence.clearTopic(topic));
|
|
1533
1575
|
} catch (error) {
|
|
1534
|
-
this.
|
|
1576
|
+
this.reportPersistenceError(error);
|
|
1535
1577
|
throw error;
|
|
1536
1578
|
}
|
|
1537
1579
|
}
|
|
@@ -1541,12 +1583,19 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1541
1583
|
if (!Number.isFinite(timestamp)) throw new TypeError("timestamp must be finite.");
|
|
1542
1584
|
if (this.replayBuffers) {
|
|
1543
1585
|
for (const [topic, messages] of this.replayBuffers) {
|
|
1544
|
-
const kept = messages.filter((message) =>
|
|
1586
|
+
const kept = messages.filter((message) => message.timestamp === void 0 || message.timestamp >= timestamp);
|
|
1545
1587
|
if (kept.length) this.replayBuffers.set(topic, kept);
|
|
1546
1588
|
else this.replayBuffers.delete(topic);
|
|
1547
1589
|
}
|
|
1548
1590
|
}
|
|
1549
|
-
if (this.replayPersistence?.clearBefore)
|
|
1591
|
+
if (this.replayPersistence?.clearBefore) {
|
|
1592
|
+
try {
|
|
1593
|
+
await this.withPersistenceRetry("clearBefore", () => this.replayPersistence.clearBefore(timestamp));
|
|
1594
|
+
} catch (error) {
|
|
1595
|
+
this.reportPersistenceError(error);
|
|
1596
|
+
throw error;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1550
1599
|
}
|
|
1551
1600
|
/** Return bounded deduplication counters for diagnostics and health checks. */
|
|
1552
1601
|
getDedupStats() {
|
|
@@ -1604,8 +1653,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1604
1653
|
async stop() {
|
|
1605
1654
|
if (!this.started) return;
|
|
1606
1655
|
this.stopping = true;
|
|
1656
|
+
this.persistenceRetryGeneration += 1;
|
|
1607
1657
|
this.trace.event({ type: "lifecycle", action: "stop" });
|
|
1608
1658
|
this.trace.stop();
|
|
1659
|
+
this.stopDedupSweep();
|
|
1660
|
+
this.stopReplayRetentionSweep();
|
|
1609
1661
|
this.topicHandlers.clear();
|
|
1610
1662
|
this.replayBuffers?.clear();
|
|
1611
1663
|
this.cluster.stop();
|
|
@@ -1616,7 +1668,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1616
1668
|
else await this.transport.stop();
|
|
1617
1669
|
} finally {
|
|
1618
1670
|
this.transportSubscribedTopics.clear();
|
|
1619
|
-
this.
|
|
1671
|
+
this.resetDedup();
|
|
1620
1672
|
this.started = false;
|
|
1621
1673
|
this.stopping = false;
|
|
1622
1674
|
this.suspended = false;
|
|
@@ -1649,7 +1701,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1649
1701
|
}
|
|
1650
1702
|
isDuplicate(message) {
|
|
1651
1703
|
if (!this.dedupEnabled || !message.messageId) return false;
|
|
1652
|
-
const now =
|
|
1704
|
+
const now = this.now();
|
|
1653
1705
|
for (const [id, timestamp] of this.seenMessageIds) {
|
|
1654
1706
|
if (now - timestamp > this.dedupTtlMs) this.seenMessageIds.delete(id);
|
|
1655
1707
|
}
|
|
@@ -1669,6 +1721,20 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1669
1721
|
}
|
|
1670
1722
|
return false;
|
|
1671
1723
|
}
|
|
1724
|
+
startDedupSweep() {
|
|
1725
|
+
if (this.dedupSweepTimer || !this.dedupEnabled || !this.dedupSweepMs) return;
|
|
1726
|
+
this.dedupSweepTimer = setInterval(() => this.pruneExpiredDedup(), this.dedupSweepMs);
|
|
1727
|
+
}
|
|
1728
|
+
stopDedupSweep() {
|
|
1729
|
+
if (this.dedupSweepTimer) clearInterval(this.dedupSweepTimer);
|
|
1730
|
+
this.dedupSweepTimer = null;
|
|
1731
|
+
}
|
|
1732
|
+
pruneExpiredDedup() {
|
|
1733
|
+
const cutoff = this.now() - this.dedupTtlMs;
|
|
1734
|
+
for (const [id, timestamp] of this.seenMessageIds) {
|
|
1735
|
+
if (timestamp < cutoff) this.seenMessageIds.delete(id);
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1672
1738
|
/** Deliver a message to every local handler registered for its topic,
|
|
1673
1739
|
* plus every handler registered with a wildcard subscription that matches
|
|
1674
1740
|
* (e.g. a handler subscribed to "chat.*" receives "chat.room.1"). */
|
|
@@ -1695,9 +1761,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1695
1761
|
buffer.push(storedMessage);
|
|
1696
1762
|
if (buffer.length > this.replayMaxPerTopic) buffer.shift();
|
|
1697
1763
|
if (this.replayPersistence) {
|
|
1698
|
-
void this.replayPersistence.append(storedMessage).catch((error) => this.
|
|
1764
|
+
void this.withPersistenceRetry("append", () => this.replayPersistence.append(storedMessage)).catch((error) => this.reportPersistenceError(error));
|
|
1699
1765
|
if (this.replayRetentionMs !== void 0 && this.replayPersistence.clearBefore) {
|
|
1700
|
-
|
|
1766
|
+
this.scheduleReplayRetentionCleanup(this.now() - this.replayRetentionMs);
|
|
1701
1767
|
}
|
|
1702
1768
|
}
|
|
1703
1769
|
}
|
|
@@ -1707,9 +1773,9 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1707
1773
|
}
|
|
1708
1774
|
try {
|
|
1709
1775
|
if (this.replayRetentionMs !== void 0 && this.replayPersistence.clearBefore) {
|
|
1710
|
-
await this.replayPersistence.clearBefore(
|
|
1776
|
+
await this.withPersistenceRetry("clearBefore", () => this.replayPersistence.clearBefore(this.now() - this.replayRetentionMs));
|
|
1711
1777
|
}
|
|
1712
|
-
for (const message of await this.replayPersistence.load()) {
|
|
1778
|
+
for (const message of await this.withPersistenceRetry("load", () => this.replayPersistence.load())) {
|
|
1713
1779
|
let buffer = this.replayBuffers.get(message.topic);
|
|
1714
1780
|
if (!buffer) {
|
|
1715
1781
|
buffer = [];
|
|
@@ -1719,7 +1785,66 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1719
1785
|
if (buffer.length > this.replayMaxPerTopic) buffer.shift();
|
|
1720
1786
|
}
|
|
1721
1787
|
} catch (error) {
|
|
1722
|
-
this.
|
|
1788
|
+
this.reportPersistenceError(error);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
scheduleReplayRetentionCleanup(cutoff) {
|
|
1792
|
+
if (!this.replayPersistence?.clearBefore) return;
|
|
1793
|
+
if (this.replayRetentionCutoff === null || cutoff > this.replayRetentionCutoff) {
|
|
1794
|
+
this.replayRetentionCutoff = cutoff;
|
|
1795
|
+
}
|
|
1796
|
+
if (this.replayRetentionCleanup) return;
|
|
1797
|
+
this.replayRetentionCleanup = (async () => {
|
|
1798
|
+
while (this.replayRetentionCutoff !== null) {
|
|
1799
|
+
const nextCutoff = this.replayRetentionCutoff;
|
|
1800
|
+
this.replayRetentionCutoff = null;
|
|
1801
|
+
try {
|
|
1802
|
+
await this.replayPersistence.clearBefore(nextCutoff);
|
|
1803
|
+
} catch (error) {
|
|
1804
|
+
this.reportPersistenceError(error);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
})().finally(() => {
|
|
1808
|
+
this.replayRetentionCleanup = null;
|
|
1809
|
+
if (this.replayRetentionCutoff !== null) {
|
|
1810
|
+
this.scheduleReplayRetentionCleanup(this.replayRetentionCutoff);
|
|
1811
|
+
}
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
startReplayRetentionSweep() {
|
|
1815
|
+
if (this.replayRetentionTimer || !this.replayRetentionMs || !this.replayRetentionSweepMs || !this.replayPersistence?.clearBefore) return;
|
|
1816
|
+
this.replayRetentionTimer = setInterval(() => {
|
|
1817
|
+
this.scheduleReplayRetentionCleanup(this.now() - this.replayRetentionMs);
|
|
1818
|
+
}, this.replayRetentionSweepMs);
|
|
1819
|
+
}
|
|
1820
|
+
stopReplayRetentionSweep() {
|
|
1821
|
+
if (this.replayRetentionTimer) clearInterval(this.replayRetentionTimer);
|
|
1822
|
+
this.replayRetentionTimer = null;
|
|
1823
|
+
}
|
|
1824
|
+
async withPersistenceRetry(persistenceOperation, operation) {
|
|
1825
|
+
const generation = this.persistenceRetryGeneration;
|
|
1826
|
+
let attempt = 0;
|
|
1827
|
+
let delay = this.persistenceRetryBackoffMs;
|
|
1828
|
+
while (true) {
|
|
1829
|
+
attempt += 1;
|
|
1830
|
+
try {
|
|
1831
|
+
if (generation !== this.persistenceRetryGeneration) throw new PersistenceRetryCancelledError();
|
|
1832
|
+
return await operation();
|
|
1833
|
+
} catch (error) {
|
|
1834
|
+
if (error instanceof PersistenceRetryCancelledError || generation !== this.persistenceRetryGeneration) {
|
|
1835
|
+
throw new PersistenceRetryCancelledError();
|
|
1836
|
+
}
|
|
1837
|
+
if (attempt >= this.persistenceRetryMaxAttempts) throw error;
|
|
1838
|
+
this.trace.event({
|
|
1839
|
+
type: "reliability",
|
|
1840
|
+
operation: "persistence_retry",
|
|
1841
|
+
persistenceOperation,
|
|
1842
|
+
attempt
|
|
1843
|
+
});
|
|
1844
|
+
if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1845
|
+
if (generation !== this.persistenceRetryGeneration) throw new PersistenceRetryCancelledError();
|
|
1846
|
+
delay = Math.min(delay * 2, 1600);
|
|
1847
|
+
}
|
|
1723
1848
|
}
|
|
1724
1849
|
}
|
|
1725
1850
|
/** Deliver buffered history to a newly-registered handler. For an exact
|
|
@@ -1757,7 +1882,7 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1757
1882
|
for (const topic of this.cluster.getSnapshot().assignedTopics) this.subscribeTransport(topic);
|
|
1758
1883
|
}
|
|
1759
1884
|
if (status === "error" && this.started && !this.stopping) {
|
|
1760
|
-
const now =
|
|
1885
|
+
const now = this.now();
|
|
1761
1886
|
if (now - this.lastRecoveryAt >= _CrossTabDataBus.RECOVERY_COOLDOWN_MS) {
|
|
1762
1887
|
this.lastRecoveryAt = now;
|
|
1763
1888
|
this.trace.event({ type: "reliability", operation: "transport_recovery", attempt: 1 });
|
|
@@ -1774,6 +1899,11 @@ var CrossTabDataBus = class _CrossTabDataBus {
|
|
|
1774
1899
|
this.trace.event({ type: "error", source: "transport" });
|
|
1775
1900
|
this.invokeHandlers(this.errorHandlers, (handler) => handler(error), "error handler");
|
|
1776
1901
|
}
|
|
1902
|
+
reportPersistenceError(error) {
|
|
1903
|
+
if (error instanceof PersistenceRetryCancelledError) return;
|
|
1904
|
+
this.trace.event({ type: "reliability", operation: "persistence_cleanup" });
|
|
1905
|
+
this.reportError(error);
|
|
1906
|
+
}
|
|
1777
1907
|
traceSubscription(action, topic) {
|
|
1778
1908
|
this.trace.event({
|
|
1779
1909
|
type: "subscription",
|
|
@@ -1931,11 +2061,13 @@ function parseDataBusPublication(value, fallbackTopic) {
|
|
|
1931
2061
|
if (!topic) return null;
|
|
1932
2062
|
const hasMetadataEnvelope = fallbackTopic !== void 0 && Object.prototype.hasOwnProperty.call(publication, "data") && (typeof publication.messageId === "string" || typeof publication.timestamp === "number");
|
|
1933
2063
|
const data = nested || fallbackTopic === void 0 || hasMetadataEnvelope ? publication.data : value;
|
|
2064
|
+
const messageId = typeof publication.messageId === "string" && publication.messageId.length > 0 ? publication.messageId : void 0;
|
|
2065
|
+
const timestamp = typeof publication.timestamp === "number" && Number.isFinite(publication.timestamp) ? publication.timestamp : void 0;
|
|
1934
2066
|
return {
|
|
1935
2067
|
topic,
|
|
1936
2068
|
data,
|
|
1937
|
-
...
|
|
1938
|
-
...
|
|
2069
|
+
...messageId === void 0 ? {} : { messageId },
|
|
2070
|
+
...timestamp === void 0 ? {} : { timestamp }
|
|
1939
2071
|
};
|
|
1940
2072
|
}
|
|
1941
2073
|
|