cross-tab-worker-databus 0.21.46 → 0.21.48
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 +40 -0
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +1 -1
- package/dist/centrifuge.js.map +2 -2
- package/dist/centrifuge.shared.worker.js.map +2 -2
- package/dist/{chunk-VUHBF4CY.js → chunk-A3AYPDMW.js} +10 -2
- package/dist/chunk-A3AYPDMW.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +9 -1
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/index.cjs +15 -2
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/replay-manager.d.ts.map +1 -1
- package/dist/core/replay-persistence.d.ts +9 -0
- package/dist/core/replay-persistence.d.ts.map +1 -1
- package/dist/core/storage-batch.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +2 -2
- package/dist/workers/port-reaper.d.ts.map +1 -1
- package/docs/api.md +1 -1
- package/docs/benchmarks.md +7 -7
- package/docs/configuration.md +18 -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 +16 -1
- package/docs/zh/release-checklist.md +1 -1
- package/docs/zh/roadmap.md +1 -1
- package/package.json +2 -2
- package/dist/chunk-VUHBF4CY.js.map +0 -7
package/docs/zh/configuration.md
CHANGED
|
@@ -67,6 +67,21 @@ const bus = new CrossTabDataBus({
|
|
|
67
67
|
| `retentionSweepMs` | `number` | — | 面向安静 topic 的周期性 durable retention sweep;需要 `retentionMs` 与实现 `clearBefore` 的适配器 |
|
|
68
68
|
| `persistenceRetry` | `{ maxAttempts, backoffMs }` | `1` / `50` | 瞬时持久化失败的有界重试;每次失败后延迟翻倍,翻倍值封顶 1600 ms,`backoffMs` 首次按原值等待 |
|
|
69
69
|
|
|
70
|
+
### 回放持久化选项
|
|
71
|
+
|
|
72
|
+
`createIndexedDbReplayPersistence<TData>(options)` 后端的选项,作为 `replay.persistence` 传入。
|
|
73
|
+
`maxPerTopic`、`pruneStrategy` 与 `retentionMs` 与上面同名的 bus 选项语义一致,但它们是**各自独立的一份
|
|
74
|
+
副本**:adapter 用传给它的那组值裁剪持久化行,而不是用 bus 的值。这里的 `maxPerTopic` 是必填而非有默认值,
|
|
75
|
+
因此 factory 与 bus 不一致时,持久化历史会按 factory 自己的值裁剪,而内存环形缓冲仍按 bus 的值。
|
|
76
|
+
|
|
77
|
+
| 配置 | 类型 | 默认值 | 说明 |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| `clusterKey` | `string` | — | 按 cluster 划分 IndexedDB 数据库,推导方式与协调层推导 storage key 完全一致(传空值时落入默认 cluster,与库中其他各处相同)。传入与 bus 相同的值,同一 origin 下运行多个 cluster 时即可每个 cluster 各得一个数据库。不传时该 origin 下所有 cluster 共用一个数据库 |
|
|
80
|
+
| `dbName` | `string` | `'cross-tab-worker-databus'` | 直接指定数据库名,优先级高于 `clusterKey` |
|
|
81
|
+
| `maxPerTopic` | `number` | 必填 | 持久化每 topic 的行数上限(正安全整数) |
|
|
82
|
+
| `pruneStrategy` | `'count' \| 'age' \| 'both'` | `'count'` | 语义同 bus 选项,作用于持久化行 |
|
|
83
|
+
| `retentionMs` | `number` | — | 持久化行 `clearBefore` 清理所用的保留窗口 |
|
|
84
|
+
|
|
70
85
|
### 去重选项
|
|
71
86
|
|
|
72
87
|
| 配置 | 类型 | 默认值 | 说明 |
|
|
@@ -266,7 +281,7 @@ Worker 模式下配置通过 `Worker` / `SharedWorker` 的 `postMessage` 发送
|
|
|
266
281
|
这是对**这些键**的约束,不是对浏览器存储整体的约束。有两个开关会把 Topic 明文和 payload 写进去:
|
|
267
282
|
|
|
268
283
|
- `channelFallback: 'storage-event'` 把每一帧协调消息整体写到 `cross-tab-worker-databus:channel:*` 之下,而一条 `CONTROL/PUBLISH` 帧同时携带它的 Topic 名称与 payload——因此这些数据会留在 `localStorage` 直到该 channel 关闭,若 tab 先退出则无限期保留。
|
|
269
|
-
- `replay.persistence`(如 `createIndexedDbReplayPersistence`)把回放历史存在 IndexedDB 的一个 object store 里,该 store 以 Topic 明文为 key,payload
|
|
284
|
+
- `replay.persistence`(如 `createIndexedDbReplayPersistence`)把回放历史存在 IndexedDB 的一个 object store 里,该 store 以 Topic 明文为 key,payload 就在其中的行里。在同一个数据库内,这个 store 只以 Topic 为 key,别无其他——从不按 tab 划分——因此共用一个数据库的两个 cluster 会读到彼此在共同 Topic 上的行。划分 cluster 的是**数据库名**:它默认取本包的 storage 前缀;向 factory 传入 `clusterKey` 时,数据库名的推导方式与协调层推导 storage key 完全一致(`clusterKey` 为空串时落入默认 cluster,与库中其他各处相同)。两者都不传时,同一 origin 下的所有 cluster 共用一个数据库,因此运行不止一个 cluster 的应用应传入 `clusterKey`;若想自选名称则传入 `dbName`,它的优先级更高。
|
|
270
285
|
|
|
271
286
|
这两个就是全部,而且是核对出来的而非声称的:`src/` 中每一处持久化写入都在 `tests/storage-writers.test.ts` 里列成表,新增一处写入——或新增一行不归属于上面两个开关却携带 Topic 的记录——都会让测试失败。
|
|
272
287
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
2. 运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`、`pnpm bench`、`pnpm test:e2e`、`pnpm bench:browser`、`pnpm verify:pack`、`pnpm verify:compat`、`pnpm verify:types` 以及 `git diff --check`(`verify:compat` 断言 `COMPAT_BASE_TAG` 基线中的 package `exports` 子路径与类型字段仍然存在;`verify:pack` 从打包产物冒烟导入完整根公共面与全部子路径的 ESM/CJS;`verify:types` 用同一基线冻结每个公共入口声明层导出的名字,并断言没有任何公共签名引用了「任何入口都未导出」的类型——纯类型导出不会在运行时产生任何键,因此 `tests/dual-format.test.ts` 的 `Object.keys()` 冻结和 `verify:compat` 都看不到它的变化。`verify:compat` 与 `verify:types` 从最近的发布 tag 解析基线,因此浅克隆或缺少 tag 的克隆需先执行 `git fetch --tags`,否则会以 "no version tag found" 失败)。
|
|
22
22
|
3. 依赖安全门禁:`pnpm audit --registry=https://registry.npmjs.org`(配置的镜像 registry 缺少 audit 端点;CI 在 verify job 中于公共 registry 运行)。任一已知漏洞公告即视为发布失败;`pnpm-workspace.yaml` overrides 钉住补丁版本。
|
|
23
23
|
4. 浏览器基准回归门禁:运行 `pnpm bench:browser`(至少两次;门禁将最新报告与之前最多五份归档报告中同一指标的中位数比较,**并且额外要求新值超过这些样本中的最大值**),随后执行 `pnpm bench:compare --fail-above-pct 50`。采用中位数基线是因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳——`dedup1000Ms` 相邻两次实测分别为 12.7 ms 与 25.6 ms,只看"上一份报告"时,一次偶发噪声就能在无代码改动的情况下击穿既定上限。第二个条件则是因为:在两档交替的样本上,中位数只有当两档保持混合时才稳定——一旦连续几份报告落在同一档,中位数本身就会跳变,这正是同一份纯注释改动在一版基线前读出 +121%、几分钟后在另一版基线前读出 −56.7% 的原因。被该条件放过的指标会打印在 `within-baseline, not gated` 下,而不是静默通过——在当前归档上实测,`publish/dedicated/perMessageMs`、`publish/shared/perMessageMs` 与 `databus/publishBatch1000Ms` 三项都落在各自五份报告的区间内,因此应把这份清单读作该指标的真实分辨率,而不是一张合格证。`publish/dedicated/perMessageMs` 同样如此:同一份代码相邻两次实测为 49.9 ms 与 71.1 ms,令门禁以 +75.7% 失败,而同一份报告里 `dedup1000Ms` 与 `traceAndPublish1000Ms` 反而*变快*——"单指标上涨、其余下降"正是噪声的特征,第三次实测为 49.4 ms 并通过。因此在采信或处理失败前先复跑并观察离散度;若改动涉及热路径,就直接量化其开销(0.20.95 有界映射改写的微基准显示三种写法均为 80–86 ns/op,落在运行间波动之内)。基线迁移(例如某指标从空操作变为真实路径)属预期内的一次性失败。用 `pnpm bench:trend` 刷新长期趋势文档,表格变化时一并提交。**复跑失败可能亲手制造出让它通过的基线,这一点已被实测。** `bench:compare` 的基线(中位数与最大值两个条件)取自最近若干份归档报告,而每一次 `pnpm bench:browser` 都会往同一个归档里追加——于是排查失败时新增的样本,就变成了裁决下一次尝试的基线。2026-09-24:主机负载均值 7.7–15.1、待发布树的非注释 `src/` 差异为 0 行,前两次实测 `publish/dedicated 77.3 ms`、`publish/shared 67.7 ms`,相对约 38/34 ms 的快档在 50% 上限上失败;随后五次复跑报告 **OK**,因为基线中位数已经滑到 `70.6`。把这些样本移出归档后的一次干净实测显示所有指标同时上涨(`dedicated +92.5%`、`shared +99.2%`、`dedup +43.4%`、`trace +21.0%`),那是资源竞争的形态,与上文"单指标上涨、其余下降"的噪声形态相反。因此:复跑之前先看负载(`uptime`);在满载主机上遇到可疑失败,就把数字连同负载一起记为"本轮推迟",并将偏离常态的样本移出基线——也不要据它们重新生成 `docs/benchmarks.md`。
|
|
24
|
-
**这条既定决策在 0.21.17 被写下,那是处于该状态下的第五个发布周期:一个发布周期里始终没有安静的窗口时,就把这份采样连同当时的负载数字一起记为"本轮推迟",而不是在满载主机上取它。** 推迟正是 `docs/benchmarks.md` 保持陈旧的原因,而"按机会更新"的这份陈旧是本步骤期望的结果,不是一道悄悄通过的门禁;真正不可接受的,是把一个受资源竞争的样本放进归档——那会变成下一次发布用来判定回归的基线。 **自 0.21.45 起,这条规则由工具执行,而不再依赖记忆,并且拒绝发生在写入之前,而不是之后。** 每份归档报告现在都会记录采样时的主机状态(`host.loadavg1m`
|
|
24
|
+
**这条既定决策在 0.21.17 被写下,那是处于该状态下的第五个发布周期:一个发布周期里始终没有安静的窗口时,就把这份采样连同当时的负载数字一起记为"本轮推迟",而不是在满载主机上取它。** 推迟正是 `docs/benchmarks.md` 保持陈旧的原因,而"按机会更新"的这份陈旧是本步骤期望的结果,不是一道悄悄通过的门禁;真正不可接受的,是把一个受资源竞争的样本放进归档——那会变成下一次发布用来判定回归的基线。 **自 0.21.45 起,这条规则由工具执行,而不再依赖记忆,并且拒绝发生在写入之前,而不是之后。** 每份归档报告现在都会记录采样时的主机状态(`host.loadavg1m` 及其核心数)——在**运行开始之前**读取,因为基准测试自身的 CPU 开销比它被判定所依据的上限还大:实测一台空闲的 8 核主机在运行开始时读数为 7.23,采样完成时已是 11.95,也就是说事后再读,量到的是基准测试而不是机器,于是每次都会拒绝一台真正空闲的主机。`bench:browser` 会判定刚采到的样本并**非零退出且不归档**,同时打印原因;已经落到磁盘上的样本,会成为此后五次比较的基线,所以针对一个已存在文件打印出的判定等于没有判定。阈值有两条,适用哪一条取决于归档本身:
|
|
25
25
|
|
|
26
26
|
- **归档中已有可比较的读数时**,超过基线中位数四倍的读数被拒绝。取比值而非绝对值,是因为归档跨机器,而负载均值脱离核心数没有意义。
|
|
27
27
|
- **归档中没有任何读数时**——这正是当前归档的全部状态,因为每份报告都早于该字段——超过主机自身核心数的读数被拒绝,因为可运行负载超过核心数按定义就是超订,且这不需要任何历史即可成立。没有这一条,守卫恰好在归档最弱的地方也最弱,而第一个在繁忙主机上采到的样本,正是那个会让二十五次发布推迟 streak 结束的样本。
|
package/docs/zh/roadmap.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cross-tab-worker-databus",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.48",
|
|
4
4
|
"description": "Framework-agnostic cross-tab data bus with Dedicated/Shared Worker clustering and Centrifuge support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"react": "^19.3.0",
|
|
142
142
|
"react-dom": "^19.3.0",
|
|
143
143
|
"typescript": "^6.0.3",
|
|
144
|
-
"typescript-eslint": "^8.
|
|
144
|
+
"typescript-eslint": "^8.71.0",
|
|
145
145
|
"vitest": "^5.0.1",
|
|
146
146
|
"vue": "^3.5.43"
|
|
147
147
|
},
|