cross-tab-worker-databus 0.20.64 → 0.20.65
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 +6 -0
- package/dist/centrifuge.js +1 -1
- package/dist/{chunk-5CP7GNU6.js → chunk-KKSZ5GUC.js} +39 -4
- package/dist/{chunk-5CP7GNU6.js.map → chunk-KKSZ5GUC.js.map} +2 -2
- package/dist/cjs/centrifuge.cjs +38 -3
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/index.cjs +38 -3
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/core/data-bus.d.ts +14 -0
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/docs/roadmap.md +5 -1
- package/docs/zh/roadmap.md +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.20.65] - 2026-09-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Added opt-in adaptive dedup TTL sampling with bounded `minMs`/`maxMs` controls and diagnostics exposure.
|
|
7
|
+
- Added replay `pruneStrategy` configuration (`count`, `age`, `both`) for memory history trimming while preserving legacy defaults.
|
|
8
|
+
|
|
3
9
|
## [0.20.64] - 2026-09-05
|
|
4
10
|
|
|
5
11
|
### Added
|
package/dist/centrifuge.js
CHANGED
|
@@ -1380,6 +1380,7 @@ var CrossTabDataBus = class {
|
|
|
1380
1380
|
replayMaxPerTopic;
|
|
1381
1381
|
replayPersistence;
|
|
1382
1382
|
replayRetentionMs;
|
|
1383
|
+
replayPruneStrategy;
|
|
1383
1384
|
replayRetentionSweepMs;
|
|
1384
1385
|
persistenceRetryMaxAttempts;
|
|
1385
1386
|
persistenceRetryBackoffMs;
|
|
@@ -1395,6 +1396,10 @@ var CrossTabDataBus = class {
|
|
|
1395
1396
|
trace;
|
|
1396
1397
|
dedupMaxEntries;
|
|
1397
1398
|
dedupTtlMs;
|
|
1399
|
+
dedupAdaptiveBounds;
|
|
1400
|
+
dedupWindowStartedAt = 0;
|
|
1401
|
+
dedupWindowAccepted = 0;
|
|
1402
|
+
dedupAdaptiveWindowMs = 5e3;
|
|
1398
1403
|
dedupSweepMs;
|
|
1399
1404
|
dedupSweepTimer = null;
|
|
1400
1405
|
dedupEnabled;
|
|
@@ -1453,6 +1458,8 @@ var CrossTabDataBus = class {
|
|
|
1453
1458
|
this.replayBuffers = replay ? /* @__PURE__ */ new Map() : null;
|
|
1454
1459
|
this.replayPersistence = replay?.persistence ?? null;
|
|
1455
1460
|
this.replayRetentionMs = replay?.retentionMs;
|
|
1461
|
+
this.replayPruneStrategy = replay?.pruneStrategy ?? "count";
|
|
1462
|
+
if (!["count", "age", "both"].includes(this.replayPruneStrategy)) throw new TypeError("replay.pruneStrategy must be count, age, or both.");
|
|
1456
1463
|
if (this.replayRetentionMs !== void 0 && (!Number.isFinite(this.replayRetentionMs) || this.replayRetentionMs <= 0)) {
|
|
1457
1464
|
throw new TypeError("replay.retentionMs must be a positive finite number.");
|
|
1458
1465
|
}
|
|
@@ -1485,6 +1492,9 @@ var CrossTabDataBus = class {
|
|
|
1485
1492
|
this.trace = new DataBusTraceReporter(trace);
|
|
1486
1493
|
this.dedupMaxEntries = dedup?.maxEntries ?? 1e3;
|
|
1487
1494
|
this.dedupTtlMs = dedup?.ttlMs ?? 6e4;
|
|
1495
|
+
this.dedupAdaptiveBounds = dedup?.adaptiveTtl;
|
|
1496
|
+
if (this.dedupAdaptiveBounds && (this.dedupAdaptiveBounds.minMs <= 0 || this.dedupAdaptiveBounds.maxMs < this.dedupAdaptiveBounds.minMs)) throw new TypeError("dedup.adaptiveTtl bounds are invalid.");
|
|
1497
|
+
this.dedupWindowStartedAt = this.now();
|
|
1488
1498
|
this.dedupSweepMs = dedup?.sweepMs;
|
|
1489
1499
|
this.dedupEnabled = dedup !== void 0;
|
|
1490
1500
|
if (!Number.isSafeInteger(this.dedupMaxEntries) || this.dedupMaxEntries <= 0) {
|
|
@@ -1758,7 +1768,8 @@ var CrossTabDataBus = class {
|
|
|
1758
1768
|
enabled: this.dedupEnabled,
|
|
1759
1769
|
tracked: this.seenMessageIds.size,
|
|
1760
1770
|
suppressed: this.dedupSuppressed,
|
|
1761
|
-
accepted: this.dedupAccepted
|
|
1771
|
+
accepted: this.dedupAccepted,
|
|
1772
|
+
...this.dedupAdaptiveBounds ? { ttlMs: this.currentDedupTtl() } : {}
|
|
1762
1773
|
};
|
|
1763
1774
|
}
|
|
1764
1775
|
/** Drop all remembered IDs and reset dedup counters. */
|
|
@@ -1930,6 +1941,7 @@ var CrossTabDataBus = class {
|
|
|
1930
1941
|
}
|
|
1931
1942
|
this.seenMessageIds.set(message.messageId, now);
|
|
1932
1943
|
this.dedupAccepted += 1;
|
|
1944
|
+
this.dedupWindowAccepted += 1;
|
|
1933
1945
|
this.trace.recordDedupAccepted();
|
|
1934
1946
|
while (this.seenMessageIds.size > this.dedupMaxEntries) {
|
|
1935
1947
|
const oldest = this.seenMessageIds.keys().next().value;
|
|
@@ -1947,11 +1959,24 @@ var CrossTabDataBus = class {
|
|
|
1947
1959
|
this.dedupSweepTimer = null;
|
|
1948
1960
|
}
|
|
1949
1961
|
pruneExpiredDedup() {
|
|
1950
|
-
const cutoff = this.now() - this.
|
|
1962
|
+
const cutoff = this.now() - this.currentDedupTtl();
|
|
1951
1963
|
for (const [id, timestamp] of this.seenMessageIds) {
|
|
1952
1964
|
if (timestamp < cutoff) this.seenMessageIds.delete(id);
|
|
1953
1965
|
}
|
|
1954
1966
|
}
|
|
1967
|
+
currentDedupTtl() {
|
|
1968
|
+
if (!this.dedupAdaptiveBounds) return this.dedupTtlMs;
|
|
1969
|
+
const now = this.now();
|
|
1970
|
+
const elapsed = now - this.dedupWindowStartedAt;
|
|
1971
|
+
if (elapsed >= this.dedupAdaptiveWindowMs) {
|
|
1972
|
+
this.dedupWindowStartedAt = now;
|
|
1973
|
+
this.dedupWindowAccepted = 0;
|
|
1974
|
+
return this.dedupAdaptiveBounds.maxMs;
|
|
1975
|
+
}
|
|
1976
|
+
const rate = this.dedupWindowAccepted / Math.max(1, elapsed);
|
|
1977
|
+
const factor = Math.min(1, rate / 0.01);
|
|
1978
|
+
return this.dedupAdaptiveBounds.maxMs - (this.dedupAdaptiveBounds.maxMs - this.dedupAdaptiveBounds.minMs) * factor;
|
|
1979
|
+
}
|
|
1955
1980
|
/** Deliver a message to every local handler registered for its topic,
|
|
1956
1981
|
* plus every handler registered with a wildcard subscription that matches
|
|
1957
1982
|
* (e.g. a handler subscribed to "chat.*" receives "chat.room.1"). */
|
|
@@ -1976,7 +2001,17 @@ var CrossTabDataBus = class {
|
|
|
1976
2001
|
}
|
|
1977
2002
|
const storedMessage = message;
|
|
1978
2003
|
buffer.push(storedMessage);
|
|
1979
|
-
if (
|
|
2004
|
+
if (this.replayPruneStrategy !== "age") {
|
|
2005
|
+
while (buffer.length > this.replayMaxPerTopic) buffer.shift();
|
|
2006
|
+
}
|
|
2007
|
+
if (this.replayPruneStrategy !== "count" && this.replayRetentionMs !== void 0) {
|
|
2008
|
+
const cutoff = this.now() - this.replayRetentionMs;
|
|
2009
|
+
while (buffer.length > 0) {
|
|
2010
|
+
const first = buffer[0];
|
|
2011
|
+
if (!first || first.timestamp === void 0 || first.timestamp >= cutoff) break;
|
|
2012
|
+
buffer.shift();
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
1980
2015
|
if (this.replayPersistence) {
|
|
1981
2016
|
void this.withPersistenceRetry("append", () => this.replayPersistence.append(storedMessage)).catch((error) => this.reportPersistenceError(error));
|
|
1982
2017
|
if (this.replayRetentionMs !== void 0 && this.replayPersistence.clearBefore) {
|
|
@@ -2329,4 +2364,4 @@ export {
|
|
|
2329
2364
|
parseDataBusPublication,
|
|
2330
2365
|
selectWorkerBackend
|
|
2331
2366
|
};
|
|
2332
|
-
//# sourceMappingURL=chunk-
|
|
2367
|
+
//# sourceMappingURL=chunk-KKSZ5GUC.js.map
|