cross-tab-worker-databus 0.21.46 → 0.21.47
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 +22 -0
- package/dist/centrifuge.js +1 -1
- package/dist/{chunk-VUHBF4CY.js → chunk-ZBA6SUFN.js} +2 -2
- package/dist/cjs/centrifuge.cjs +1 -1
- package/dist/cjs/index.cjs +7 -2
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/core/replay-persistence.d.ts +9 -0
- package/dist/core/replay-persistence.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +2 -2
- package/docs/api.md +1 -1
- package/docs/benchmarks.md +7 -7
- package/docs/configuration.md +1 -1
- package/docs/release-checklist.md +1 -1
- package/docs/roadmap.md +1 -1
- package/docs/zh/api.md +1 -1
- package/docs/zh/benchmarks.md +7 -7
- package/docs/zh/configuration.md +1 -1
- package/docs/zh/release-checklist.md +1 -1
- package/docs/zh/roadmap.md +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-VUHBF4CY.js.map → chunk-ZBA6SUFN.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## [0.21.47] - 2026-09-30
|
|
2
|
+
|
|
3
|
+
One new option, one guard that could not pass, and the first browser-benchmark sample in twenty-five tags. No existing behavior changed: the option is additive, and the one case that documents how the replay store behaves today is unchanged.
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`createIndexedDbReplayPersistence` accepts `clusterKey`, and the IndexedDB store is namespaced by it.** The replay store is the one place in the library where `clusterKey` — documented everywhere else as the boundary for storage keys and the BroadcastChannel namespace — did not apply: its database name defaulted to the package's storage prefix, and the store is keyed by the plaintext Topic, so two clusters in one origin read each other's rows for any Topic they share. Pass the same `clusterKey` the bus gets and the database name is derived exactly as the coordination plane derives its storage keys, so an application running more than one cluster gets one namespace per cluster without naming databases by hand.
|
|
8
|
+
- **Two derivations, both pinned.** The name uses `createOpaqueKey(clusterKey || '__default__')` — the *same* function and the *same* empty-key fallback the coordination plane uses, because `''` and `'__default__'` are one cluster everywhere else in the library; hashing `''` on its own would open a database no bus ever reads, and the symptom would be silently empty replay rather than an error. And an explicit `dbName` still wins over a supplied `clusterKey`, because it is the documented escape hatch for an application that wants its own naming, and silently overriding a name the caller typed would be worse than the inconsistency this option removes.
|
|
9
|
+
- **It is additive, and deliberately not a changed default.** Namespacing by default is the only shape that fixes the hole with no opt-in, and it is the wrong trade: it would move every existing caller's rows into a database no bus opens, surfacing as silently empty replay rather than as an error. Omitting `clusterKey` still shares, so nothing moves for anyone who does not ask for it.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **The browser benchmark's host-load guard was reading the host _after_ the benchmark had consumed the CPU, so it measured itself and could never pass.** Introduced in `0.21.45`, it compares a sample's load against a ceiling. The reading was taken at archive time — after Chrome launched, the demo server spawned and the whole mode matrix ran — and on an 8-core host that self-inflicted cost exceeds the ceiling: a host idle long enough to read **7.23** was at **11.95** by the time a sample completed, and a second run traced 11.6 rising to 13.0 mid-run and decaying to 8.96. So the guard would have refused a genuinely idle machine on every attempt, turning "wait for a quiet window" into "impossible by construction", with no error anywhere to say so. The reading is now taken before any of the run's own work, which is the only reading that answers the question the guard asks: was this machine busy for something *other* than being benchmarked.
|
|
14
|
+
|
|
15
|
+
### Verification
|
|
16
|
+
|
|
17
|
+
- `pnpm check` — 39 test files, **1019 tests**, typecheck, build, 5 perf gates; `pnpm lint`; the bench and documentation gates.
|
|
18
|
+
- Three mutants on the new option, each applied alone and restored, with the applied-line count printed and asserted before the run: accepting and ignoring `clusterKey`, hashing the empty key on its own, and letting `clusterKey` override an explicit `dbName`. Each dies to a distinct case.
|
|
19
|
+
- Two mutants on the guard's reading placement, pinned as a text gate over the script because the call sits inside `main()` behind a server spawn and a browser launch: moving the reading back to archive time, and deleting it.
|
|
20
|
+
- **The first browser-benchmark sample in 25 tags**, and the first of 92 to record host state: `host: { loadavg1m: 7.88, cpus: 8 }` on `darwin`. `pnpm bench:compare --fail-above-pct 50` exits 0 — `publish/dedicated` +11.4 %, `publish/shared` +11.5 %, `wildcardDispatch1000Ms` +13.8 %, `publishBatch1000Ms` +16.3 %, `dedup1000Ms` +0.5 %, `traceAndPublish1000Ms` −8.1 % — and `docs/benchmarks.md` plus its zh mirror regenerate from 92 reports. Those deltas span 25 releases against a single prior sample rather than any change in this release, which is why the gate requires beating the *highest* of the five baseline samples and not merely the median.
|
|
21
|
+
- `pnpm audit` on the public registry, clean and independently re-derived from the installed version against the published advisory ranges rather than from the tool's exit code.
|
|
22
|
+
|
|
1
23
|
## [0.21.46] - 2026-09-30
|
|
2
24
|
|
|
3
25
|
`0.21.45` shipped a guard whose own release note explained why it did not yet work in the case that mattered. This is that case, fixed, plus the dependency the release's audit should have caught and did not. No library behavior, export, option, default, frame or storage key changed; the coverage floors and the zero-count arm ledger are `0.21.45`'s.
|
package/dist/centrifuge.js
CHANGED
|
@@ -2540,7 +2540,7 @@ var SDK_VERSION = (
|
|
|
2540
2540
|
// declaration's type is `string | undefined` and the export's is `string`
|
|
2541
2541
|
// (dropping the conditional is TS2322, measured). Recorded here so the leg reads
|
|
2542
2542
|
// as a shape the harness cannot reach rather than as a case nobody exercised.
|
|
2543
|
-
true ? "0.21.
|
|
2543
|
+
true ? "0.21.47" : ""
|
|
2544
2544
|
);
|
|
2545
2545
|
|
|
2546
2546
|
// src/core/data-bus.ts
|
|
@@ -3793,4 +3793,4 @@ export {
|
|
|
3793
3793
|
parseDataBusPublication,
|
|
3794
3794
|
selectWorkerBackend
|
|
3795
3795
|
};
|
|
3796
|
-
//# sourceMappingURL=chunk-
|
|
3796
|
+
//# sourceMappingURL=chunk-ZBA6SUFN.js.map
|
package/dist/cjs/centrifuge.cjs
CHANGED
|
@@ -2669,7 +2669,7 @@ var SDK_VERSION = (
|
|
|
2669
2669
|
// declaration's type is `string | undefined` and the export's is `string`
|
|
2670
2670
|
// (dropping the conditional is TS2322, measured). Recorded here so the leg reads
|
|
2671
2671
|
// as a shape the harness cannot reach rather than as a case nobody exercised.
|
|
2672
|
-
true ? "0.21.
|
|
2672
|
+
true ? "0.21.47" : ""
|
|
2673
2673
|
);
|
|
2674
2674
|
|
|
2675
2675
|
// src/core/data-bus.ts
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2635,7 +2635,7 @@ var SDK_VERSION = (
|
|
|
2635
2635
|
// declaration's type is `string | undefined` and the export's is `string`
|
|
2636
2636
|
// (dropping the conditional is TS2322, measured). Recorded here so the leg reads
|
|
2637
2637
|
// as a shape the harness cannot reach rather than as a case nobody exercised.
|
|
2638
|
-
true ? "0.21.
|
|
2638
|
+
true ? "0.21.47" : ""
|
|
2639
2639
|
);
|
|
2640
2640
|
|
|
2641
2641
|
// src/core/data-bus.ts
|
|
@@ -3829,10 +3829,15 @@ function holdLastFinite(source) {
|
|
|
3829
3829
|
}
|
|
3830
3830
|
|
|
3831
3831
|
// src/core/replay-persistence.ts
|
|
3832
|
+
function resolveDbName(options) {
|
|
3833
|
+
if (options.dbName !== void 0) return options.dbName;
|
|
3834
|
+
if (options.clusterKey === void 0) return DEFAULT_STORAGE_PREFIX;
|
|
3835
|
+
return `${DEFAULT_STORAGE_PREFIX}:${createOpaqueKey(options.clusterKey || "__default__")}`;
|
|
3836
|
+
}
|
|
3832
3837
|
function createIndexedDbReplayPersistence(options) {
|
|
3833
3838
|
const indexedDb = globalThis.indexedDB;
|
|
3834
3839
|
if (!indexedDb) throw new Error("IndexedDB is unavailable in this environment.");
|
|
3835
|
-
const dbName = options
|
|
3840
|
+
const dbName = resolveDbName(options);
|
|
3836
3841
|
const storeName = "replay";
|
|
3837
3842
|
const maxPerTopic = options.maxPerTopic;
|
|
3838
3843
|
const pruneStrategy = options.pruneStrategy ?? PRUNE_STRATEGY.COUNT;
|