cross-tab-worker-databus 0.20.71 → 0.20.85
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 +204 -2
- package/README.md +8 -0
- package/README.zh.md +4 -0
- package/dist/centrifuge-protocol.d.ts +59 -26
- package/dist/centrifuge-protocol.d.ts.map +1 -1
- package/dist/centrifuge-session.d.ts +9 -0
- package/dist/centrifuge-session.d.ts.map +1 -1
- package/dist/centrifuge.d.ts +12 -2
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +168 -88
- package/dist/centrifuge.js.map +3 -3
- package/dist/centrifuge.shared.worker.js +146 -38
- package/dist/centrifuge.shared.worker.js.map +3 -3
- package/dist/centrifuge.worker.js +140 -33
- package/dist/centrifuge.worker.js.map +3 -3
- package/dist/{chunk-D2SIT473.js → chunk-PW63EWIK.js} +1090 -494
- package/dist/chunk-PW63EWIK.js.map +7 -0
- package/dist/chunk-TZ7ZP7YD.js +175 -0
- package/dist/chunk-TZ7ZP7YD.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +1403 -637
- package/dist/cjs/centrifuge.cjs.map +4 -4
- package/dist/cjs/hooks.cjs +37 -2
- package/dist/cjs/hooks.cjs.map +3 -3
- package/dist/cjs/index.cjs +1453 -730
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/cjs/vue.cjs +45 -2
- package/dist/cjs/vue.cjs.map +3 -3
- package/dist/core/cluster.d.ts +40 -4
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/data-bus.d.ts +93 -69
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/core/dedup-manager.d.ts +98 -0
- package/dist/core/dedup-manager.d.ts.map +1 -0
- package/dist/core/environment.d.ts +43 -3
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/replay-manager.d.ts +128 -0
- package/dist/core/replay-manager.d.ts.map +1 -0
- package/dist/core/replay-persistence.d.ts +2 -1
- package/dist/core/replay-persistence.d.ts.map +1 -1
- package/dist/core/routing.d.ts +22 -3
- package/dist/core/routing.d.ts.map +1 -1
- package/dist/core/storage-batch.d.ts +0 -4
- package/dist/core/storage-batch.d.ts.map +1 -1
- package/dist/core/trace.d.ts +55 -15
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/core/types.d.ts +58 -9
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/hooks.d.ts +12 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +28 -2
- package/dist/hooks.js.map +2 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +228 -162
- package/dist/index.js.map +3 -3
- package/dist/utils/constants.d.ts +170 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/error-utils.d.ts +28 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/metadata.d.ts +16 -0
- package/dist/utils/metadata.d.ts.map +1 -0
- package/dist/utils/storage-utils.d.ts +24 -0
- package/dist/utils/storage-utils.d.ts.map +1 -0
- package/dist/utils/validation.d.ts +76 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/vue.d.ts +13 -1
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +36 -2
- package/dist/vue.js.map +2 -2
- package/dist/websocket.d.ts +6 -1
- package/dist/websocket.d.ts.map +1 -1
- package/dist/worker-mode.d.ts +6 -2
- package/dist/worker-mode.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/api.md +122 -2
- package/docs/architecture.md +80 -0
- package/docs/benchmarks.md +24 -0
- package/docs/capabilities.md +24 -3
- package/docs/configuration.md +58 -0
- package/docs/getting-started.md +35 -0
- package/docs/release-checklist.md +28 -5
- package/docs/roadmap.md +74 -5
- package/docs/zh/README.md +2 -1
- package/docs/zh/api.md +121 -2
- package/docs/zh/architecture.md +49 -0
- package/docs/zh/benchmarks.md +24 -0
- package/docs/zh/capabilities.md +21 -3
- package/docs/zh/configuration.md +53 -0
- package/docs/zh/getting-started.md +35 -0
- package/docs/zh/release-checklist.md +29 -6
- package/docs/zh/roadmap.md +86 -5
- package/package.json +39 -16
- package/dist/chunk-D2SIT473.js.map +0 -7
package/docs/zh/configuration.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
| `transport` | `DataBusTransport<TConfig, TData>` | 必填 | 真实连接和订阅实现 |
|
|
13
13
|
| `initialConfig` | `TConfig` | 无 | 自动启动时传给 transport |
|
|
14
14
|
| `autoStart` | `boolean` | 传入 `initialConfig` 时为 `true` | 是否在创建实例后自动启动 |
|
|
15
|
+
| `recovery.cooldownMs` | `number` | `1000` | 出错后自动重开 transport 前的最小延迟 |
|
|
16
|
+
| `recovery.maxAttempts` | `number` | `Infinity` | 每轮恢复序列的最大自动重开次数;显式订阅需求仍可继续重试 |
|
|
15
17
|
| `storagePrefix` | `string` | `cross-tab-worker-databus` | storage key 和 BroadcastChannel 的命名空间 |
|
|
16
18
|
| `maxActiveWorkers` | `number` | `3` | 可作为 Topic owner 的最大 Worker 数 |
|
|
17
19
|
| `heartbeatIntervalMs` | `number` | `3000` | Worker 心跳间隔 |
|
|
@@ -54,6 +56,27 @@ const bus = new CrossTabDataBus({
|
|
|
54
56
|
|
|
55
57
|
`replay.persistenceRetry` 可选地控制瞬时持久化失败的恢复。`maxAttempts` 是总尝试次数(默认 `1`),`backoffMs` 是首次重试前的延迟(默认 `50`);延迟会指数增长并封顶。最终失败仍沿用现有 `onError` 和 reliability 行为。
|
|
56
58
|
|
|
59
|
+
### Replay 选项
|
|
60
|
+
|
|
61
|
+
| 配置 | 类型 | 默认值 | 说明 |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| `maxPerTopic` | `number` | `100` | 每个 topic 最多缓冲的 publication 数;超出时先淘汰最旧条目(正安全整数) |
|
|
64
|
+
| `persistence` | `DataBusReplayPersistence` | — | 可选持久化后端(`createIndexedDbReplayPersistence`);省略则历史仅存内存 |
|
|
65
|
+
| `retentionMs` | `number` | — | 生产者时间戳保留窗口;早于 cutoff 的历史通过适配器的 `clearBefore` 清理 |
|
|
66
|
+
| `pruneStrategy` | `'count' \| 'age' \| 'both'` | `'count'` | `count` 按 `maxPerTopic` 截断;`age` 按 `retentionMs` 清理;`both` 两者都应用。`age` 未配置 `retentionMs` 时无 age 可依,回退为数量上限 |
|
|
67
|
+
| `retentionSweepMs` | `number` | — | 面向安静 topic 的周期性 durable retention sweep;需要 `retentionMs` 与实现 `clearBefore` 的适配器 |
|
|
68
|
+
| `persistenceRetry` | `{ maxAttempts, backoffMs }` | `1` / `50` | 瞬时持久化失败的有界重试;延迟指数增长并封顶 |
|
|
69
|
+
|
|
70
|
+
### 去重选项
|
|
71
|
+
|
|
72
|
+
| 配置 | 类型 | 默认值 | 说明 |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| `maxEntries` | `number` | `1000` | 记忆的 message ID 上限,超出时先淘汰最旧(FIFO)条目(正安全整数) |
|
|
75
|
+
| `ttlMs` | `number` | `60000` | 记忆 ID 抑制重复的时长(正有限值) |
|
|
76
|
+
| `sweepMs` | `number` | — | 可选的周期性清理,使安静 ID 过期;默认关闭 |
|
|
77
|
+
| `now` | `() => number` | `Date.now` | 可注入时钟,便于确定性 TTL 测试与非墙钟宿主 |
|
|
78
|
+
| `adaptiveTtl` | `{ minMs, maxMs }` | — | 可选有界自适应 TTL:近期消息速率高时窗口向 `minMs` 收紧,安静时放宽到 `maxMs`(两者必须同时提供,且 `minMs <= maxMs`) |
|
|
79
|
+
|
|
57
80
|
启用 trace 后,每次在最终尝试之前发生的重试都会发出有界 `reliability` 事件:`operation: persistence_retry`,并包含 `persistenceOperation`(`load`、`append`、`clear`、`clearTopic` 或 `clearBefore`)和失败的尝试次数。不包含 payload、URL、凭证或错误正文。
|
|
58
81
|
|
|
59
82
|
WebSocket 二进制帧可能以 `ArrayBuffer` 或浏览器 `Blob` 到达;两者使用相同的紧凑二进制 publication 格式。Blob 转换是异步的,转换失败会通过 transport error handler 报告。
|
|
@@ -98,6 +121,29 @@ active 集合只在 Topic 需要选择新 owner 时使用。已有 owner Worker
|
|
|
98
121
|
- `2-3`:在资源复用和故障恢复之间取得平衡。
|
|
99
122
|
- 更大值:适合 Topic 很多且单连接存在服务端限制的场景。
|
|
100
123
|
|
|
124
|
+
### 自适应 owner 加权
|
|
125
|
+
|
|
126
|
+
默认情况下新 Topic 分配给拥有最少 Topic 的 owner。可选的 `loadWeighting` 加入流量与调度信号,使新 route 偏向更空闲、更健康的 Worker——已有 route 保持 sticky,永不被迁移。
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const bus = createCentrifugeDataBus({
|
|
130
|
+
connection: { url: getConnectionUrl() },
|
|
131
|
+
loadWeighting: {
|
|
132
|
+
messageRateWeight: 0.5, // 每条消息/秒的权重
|
|
133
|
+
byteRateWeight: 0.001, // 每字节/秒的权重
|
|
134
|
+
scheduleLagWeight: 2 // 心跳调度滞后比率的权重
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| 选项 | 默认值 | 作用 |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `messageRateWeight` | `0` | 每个 Worker 按心跳窗口采样自身的 fan-out 消息速率,归一化速率计入有效负载。 |
|
|
142
|
+
| `byteRateWeight` | `0` | 同上,针对近似 payload 字节数/秒。 |
|
|
143
|
+
| `scheduleLagWeight` | `0` | 加权调度滞后比率(`overrunMs ÷ windowMs`)。事件循环饥饿会让心跳延迟,从而引导新 route 远离被节流的 Worker。 |
|
|
144
|
+
|
|
145
|
+
所有权重默认 `0`,保持纯按 Topic 数的 legacy 行为字节级不变。每个权重必须是非负有限数;负数或非有限值会在构造时抛出 `TypeError`,因为负权重会把新 route 导向**最繁忙**的 Worker。每个 Worker 的采样(`WorkerThroughputSample`)随心跳发布,含 `windowMs`、`messageCount`、`byteCount`、`overrunMs`、`sampledAt`。
|
|
146
|
+
|
|
101
147
|
## Centrifuge 配置
|
|
102
148
|
|
|
103
149
|
`createCentrifugeDataBus<TData>(options)` 的主要配置:
|
|
@@ -112,6 +158,7 @@ active 集合只在 Topic 需要选择新 owner 时使用。已有 owner Worker
|
|
|
112
158
|
| `heartbeatIntervalMs` | `number` | `10000` | SharedWorker PING 心跳间隔(见下方 SharedWorker 会话回收);传 `Infinity` 完全禁用心跳。与 Core 集群心跳(默认 3000 ms,通过 localStorage 跟踪 worker 存活)相互独立 |
|
|
113
159
|
| `workerFactory` | `() => Worker` | 内置 Worker | 测试或自定义 Worker 加载方式 |
|
|
114
160
|
| `sharedWorkerFactory` | `() => SharedWorker` | 内置 SharedWorker | 测试或自定义 SharedWorker 加载方式 |
|
|
161
|
+
| `credentialProvider` | `{ getToken?, getChannelToken? }` | `undefined` | 异步凭证刷新桥:Worker 向主线程请求每个新 token(`getToken` / `getChannelToken`),由该 provider 从应用上下文提供。必要原因:函数型 Centrifuge 选项无法 structured-clone 进 Worker |
|
|
115
162
|
| 其他 Core 配置 | 对应类型 | Core 默认值 | `storagePrefix`、心跳、TTL 等 |
|
|
116
163
|
|
|
117
164
|
```ts
|
|
@@ -144,6 +191,12 @@ const bus = createCentrifugeDataBus({
|
|
|
144
191
|
|
|
145
192
|
`sharedWorkerFactory` 和 `workerFactory` 都未提供时,transport 在启动时检测全局 `SharedWorker` / `Worker` 能力。提供自定义 factory 时,对应后端视为可用,避免在 Node、SSR 或嵌入环境中被全局能力检测误判。各模式都会执行相同的结构化克隆校验,配置和 `publish` 数据必须可结构化克隆。
|
|
146
193
|
|
|
194
|
+
## 协调通道降级(BroadcastChannel 不可用)
|
|
195
|
+
|
|
196
|
+
当 `BroadcastChannel` 不可用(部分 WebView、旧浏览器)时,集群通常降级为本地模式:transport 可用,但 Tab 之间不协调 owner。
|
|
197
|
+
|
|
198
|
+
`createBrowserEnvironment({ channelFallback: 'storage-event' })` 可选择启用基于 localStorage `storage` 事件的降级 `ClusterChannel`,保留跨 Tab 协调能力。该能力为 opt-in,原因是安全权衡:BroadcastChannel 消息仅存在于内存,而降级通道会把协调载荷(含明文 Topic 名称)写入 localStorage 的 `cross-tab-worker-databus:channel:` 键空间——至少短暂落盘,Tab 崩溃后可能长期留存。通道关闭时会清除该键。
|
|
199
|
+
|
|
147
200
|
## SharedWorker 会话回收
|
|
148
201
|
|
|
149
202
|
`MessagePort` 没有 `close` 事件,因此 SharedWorker 无法在 Tab 崩溃或关闭时获知(除非收到 `STOP` 消息)。为避免泄漏已死 Tab 的 `CentrifugeSession`(及其 WebSocket),transport 定期向 SharedWorker 发送 **PING 心跳**,SharedWorker 运行一个**回收器**来关闭超过静默超时的端口会话。
|
|
@@ -168,3 +168,38 @@ const config = await loadTransportConfig();
|
|
|
168
168
|
await bus.start(config);
|
|
169
169
|
bus.subscribe('resource.changed', handleResourceEvent);
|
|
170
170
|
```
|
|
171
|
+
|
|
172
|
+
## 10. 健康摘要与协调降级
|
|
173
|
+
|
|
174
|
+
就绪探针与仪表盘可直接消费单对象健康判定,无需自行拼装诊断:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const health = bus.getHealthSummary();
|
|
178
|
+
// { healthy: true, state: 'healthy', recovery: { attempt, … }, lastFailure: null, … }
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
React 与 Vue 适配器提供 `useCrossTabHealth`,在状态变化、错误与轮询间隔时刷新。
|
|
182
|
+
|
|
183
|
+
当 `BroadcastChannel` 不可用时,各 Tab 通常退化为本地模式。可选择启用基于 localStorage storage 事件的降级通道:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import { createBrowserEnvironment } from 'cross-tab-worker-databus';
|
|
187
|
+
|
|
188
|
+
const bus = new CrossTabDataBus({
|
|
189
|
+
/* … */
|
|
190
|
+
environment: createBrowserEnvironment({ channelFallback: 'storage-event' })
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
该能力为 opt-in:启用后协调载荷(明文 Topic 名称)会写入 localStorage,详见 [configuration.md](./configuration.md#协调通道降级broadcastchannel-不可用)。
|
|
195
|
+
|
|
196
|
+
## 11. 升级与弃用
|
|
197
|
+
|
|
198
|
+
在 `1.0.0` 之前,SDK 允许增量新增,并在明确的弃用周期后才移除 API。根导出面由回归套件与 tag 间兼容性门禁钉住,意外删除会令 CI 失败,而不是静默破坏既有消费者。
|
|
199
|
+
|
|
200
|
+
升级时请注意:
|
|
201
|
+
|
|
202
|
+
- 逐版阅读当前版本到目标版本之间每个版本的 CHANGELOG。每次移除都会在其中明确指出,且弃用周期只在小版本间顺延。
|
|
203
|
+
- 若运行时 `console.warn` 提到某弃用别名,请在下一个小版本前迁移——该别名在告警首次出现后至少再存活一个小版本。
|
|
204
|
+
- 混版本 Tab 仍可协调:集群在诊断中携带协议版本(`getDiagnostics().protocol`),协议变更后 legacy 消息帧至少再解析一个小版本。
|
|
205
|
+
- 1.0 前,请优先使用 [api.md](./api.md) 中的文档化入口与 [capabilities.md](./capabilities.md) 的能力矩阵。每次发布都会对 ESM 与 CommonJS 消费者做打包验证。
|
|
@@ -2,16 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
每个 1.0.0 之前的版本都按此清单执行。仓库不由助手执行发布;完成打包验证并人工审阅后,再手动运行 npm 命令。
|
|
4
4
|
|
|
5
|
+
## 公共 API 稳定性与弃用策略(1.0 之前)
|
|
6
|
+
|
|
7
|
+
- 根导出面由 `tests/dual-format.test.ts`(冻结测试)与 `scripts/verify-version-compat.mjs`(tag 间兼容门禁)钉住。新增或删除导出是经过评审的刻意变更;同一提交中必须同步更新 `docs/api.md` 与 CHANGELOG。
|
|
8
|
+
- 1.0 前的破坏性变更仅在走完弃用周期后才允许:legacy 别名至少保留一个小版本,首次使用时 `console.warn` 提示,且只在 CHANGELOG 明确标注移除的小版本中删除。
|
|
9
|
+
- 协议别名(worker/cluster/transport 消息形态)遵循同一规则:弃用后至少一个小版本继续解析 legacy 帧,保证混版本 peer 兼容(见 `getDiagnostics().protocol` 的协议版本诊断)。
|
|
10
|
+
- 晋升 `1.0.0` 要求公共 API 与协议弃用策略正式冻结,并发布迁移指南(见 `docs/roadmap.md` 的 0.13.0 candidates)。
|
|
11
|
+
|
|
12
|
+
## 自动化门禁(CI)
|
|
13
|
+
|
|
14
|
+
`CI` 工作流的 `verify` job 在每次 push 与 pull request 上运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`(`vitest.config.ts` 中的下限:语句 85% / 分支 80% / 函数 90% / 行 85%)、`pnpm verify:compat`、`pnpm verify:pack`、`pnpm bench` 与 `pnpm audit`;`browser` job 运行 Playwright E2E 套件。`Release` 工作流在发布前重跑 `verify:compat` 与 `verify:pack`,随后执行阻塞式 `verify:published` 门禁。两个工作流的 checkout 均使用 `fetch-depth: 0` + `fetch-tags: true`,因为 `verify:compat` 需要从最近的发布 tag 解析基线。
|
|
15
|
+
|
|
16
|
+
只有 `pnpm bench:browser` / `pnpm bench:compare` 保持仅本地执行:共享 runner 的计时噪声会让数值型 CI 门禁不可靠。
|
|
17
|
+
|
|
5
18
|
## 打 tag 前
|
|
6
19
|
|
|
7
20
|
1. 更新 `package.json`、`CHANGELOG.md` 和中英文 roadmap。
|
|
8
|
-
2. 运行 `pnpm check`、`pnpm lint`、`pnpm bench`、`pnpm test:e2e`、`pnpm bench:browser`、`pnpm verify:pack` 以及 `git diff --check
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
21
|
+
2. 运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`、`pnpm bench`、`pnpm test:e2e`、`pnpm bench:browser`、`pnpm verify:pack`、`pnpm verify:compat` 以及 `git diff --check`(`verify:compat` 断言 `COMPAT_BASE_TAG` 基线中的 package `exports` 子路径与类型字段仍然存在;`verify:pack` 从打包产物冒烟导入完整根公共面与全部子路径的 ESM/CJS。`verify:compat` 从最近的发布 tag 解析基线,因此浅克隆或缺少 tag 的克隆需先执行 `git fetch --tags`,否则会以 "no version tag found" 失败)。
|
|
22
|
+
3. 依赖安全门禁:`pnpm audit --registry=https://registry.npmjs.org`(配置的镜像 registry 缺少 audit 端点;CI 在 verify job 中于公共 registry 运行)。任一已知漏洞公告即视为发布失败;`pnpm-workspace.yaml` overrides 钉住补丁版本。
|
|
23
|
+
4. 浏览器基准回归门禁:运行两次 `pnpm bench:browser` 后执行 `pnpm bench:compare --fail-above-pct 50`(50% 上限用于吸收共享 runner 的无关噪声,参见已知的共享 runner 抖动说明);基线迁移(例如某指标从空操作变为真实路径)属预期内的一次性失败。用 `pnpm bench:trend` 刷新长期趋势文档,表格变化时一并提交。
|
|
24
|
+
5. 用 `npm pack --dry-run --json` 确认发布包只包含预期文件。
|
|
25
|
+
6. 提交、给精确版本打 tag,并推送 `main --tags`。
|
|
26
|
+
|
|
27
|
+
## 安全与依赖扫描
|
|
28
|
+
|
|
29
|
+
仓库配置了 CodeQL(`javascript-typescript`,push/PR/每周)与 Dependabot(npm + GitHub Actions 每周更新)。CodeQL 告警会作为 PR check 暴露;Dependabot PR 在合并前必须通过其 verify(全量 check)与 CodeQL 检查,浏览器 E2E 的已知共享 runner 抖动按既有处理方式重跑确认。
|
|
30
|
+
|
|
31
|
+
## 打 tag 的发布工作流
|
|
32
|
+
|
|
33
|
+
推送版本 tag 会触发 `Release` GitHub Action:先跑 `pnpm check` 与 `pnpm lint`(tag 可能指向从未通过 CI lint 步骤的提交),再跑 `verify:compat` 与 `verify:pack`,从 `CHANGELOG` 对应章节生成 GitHub release,配置了 `NPM_TOKEN` 时自动发布到 npm,然后运行与手动执行相同预算的**阻塞式**消费者验证(`PUBLISHED_VERIFY_ATTEMPTS=24`、`PUBLISHED_VERIFY_DELAY_MS=5000`)。已发布包若无法被干净消费者导入,工作流即失败——任何 `verify:published` 失败都应视为发布失败,修复后重新发布该 tag。未配置 token 时跳过发布步骤,但验证仍会针对 npm 上已有的版本(例如手动发布的)通过。
|
|
11
34
|
|
|
12
|
-
##
|
|
35
|
+
## 发布(手动场景)
|
|
13
36
|
|
|
14
|
-
|
|
37
|
+
未在工作流配置 `NPM_TOKEN` 时,从对应 tag 的工作树手动运行 `npm publish --access public`。已经存在于 npm 的版本不能重复发布;npm 缺失的历史版本必须从对应 git tag 重建并逐个审阅,不能把当前工作树伪装成旧版本发布。
|
|
15
38
|
|
|
16
39
|
## 发布后
|
|
17
40
|
|
|
@@ -19,4 +42,4 @@
|
|
|
19
42
|
2. 在干净消费者中安装已发布版本或 tarball,并导入主入口及所有公开子路径。
|
|
20
43
|
3. 将结果记录到发布说明。在公开 API 和协议弃用策略明确冻结前,不进入 `1.0.0`。
|
|
21
44
|
|
|
22
|
-
|
|
45
|
+
打 tag 的发布工作流已自动执行上述消费者验证;仅在需要离线复验时才手动运行 `PUBLISHED_VERSION=<version> pnpm verify:published`。只有遇到异常慢的镜像才需要调整 `PUBLISHED_VERIFY_ATTEMPTS` 和 `PUBLISHED_VERIFY_DELAY_MS`。
|
package/docs/zh/roadmap.md
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
# 路线图
|
|
2
2
|
|
|
3
|
-
0.20.
|
|
3
|
+
0.20.85 正在推进。项目会先持续完成可靠性与协议兼容性的中版本迭代,再进入 1.0.0 稳定性冻结。
|
|
4
|
+
|
|
5
|
+
## 0.20.85 已完成范围
|
|
6
|
+
|
|
7
|
+
- 新增固定种子的属性测试套件(`tests/property.test.ts`):针对纯热路径函数与有状态管理器,覆盖有限性/全函数性、与顺序无关的选择、循环安全的大小估算、publication topic/元数据有效性、`serializeError` 可克隆性,以及长时间随机操作序列下的 dedup/replay 上界。
|
|
8
|
+
- `effectiveWorkerLoad` 对损坏的存储基础负载保持全函数性——非有限值(JSON `1e999` → `Infinity`)不再泄漏进 owner 选择并重新引入数组顺序依赖。
|
|
9
|
+
- `approximatePayloadBytes` 增加深度上界,循环 payload(structured clone 会保留循环)不再使回放字节占用或自适应负载采样栈溢出。
|
|
10
|
+
- `serializeError` 始终产出可结构化克隆的结果;不可克隆的 context(函数/Symbol)会被丢弃,而不是让错误上报本身抛出 `DataCloneError`。
|
|
11
|
+
- 当 `pruneStrategy: 'age'` 未配置 `retentionMs` 时,回放历史重新受上界约束:内存环与 IndexedDB 记录均应用数量上限。
|
|
12
|
+
|
|
13
|
+
## 0.20.84 已完成范围
|
|
14
|
+
|
|
15
|
+
- 发布/CI 门禁由“文档约定”变为强制执行:`pnpm test:coverage`、`pnpm verify:compat`、`pnpm verify:pack` 进入 CI verify job,Release 工作流在发布前重跑 lint + compat + pack,两个 checkout 均拉取完整历史与 tag 以便解析 compat 基线。
|
|
16
|
+
- 协调恢复加固:交接 ACK 丢失、owner 崩溃或前任 owner 退出后,均由 worker-TTL 门禁的重新选举恢复,采用单写者与投影负载分摊;每次路由确认 / 迁移 / 恢复都会发出有界的 `reliability` trace 事件。
|
|
17
|
+
- 三个真实正确性修复:Vue `useCrossTabDataBus` 卸载泄漏(pending start 可能创建无人拥有的 bus)、自适应 dedup TTL 未在热路径生效,以及 `effectiveWorkerLoad` 会把损坏的存储 load 造成的非有限评分泄漏回 owner 选择。
|
|
18
|
+
- 产品 demo 可观测性:事件流渲染 reliability / subscription / coordination trace 事件,混沌开关在真实浏览器中演练丢 ACK 与崩溃恢复路径,配置面板显示当前混沌模式。
|
|
19
|
+
- 覆盖与工具链:`ReplayManager` / `DedupManager` 直接测试套件、transport 错误隔离与部分元数据覆盖、vitest 5(基准 API 已迁移)与 eslint 10 lint 配置;TypeScript 7 因 typescript-eslint 未支持而继续递延。
|
|
20
|
+
|
|
21
|
+
## 0.20.83 已完成范围
|
|
22
|
+
|
|
23
|
+
- 健康钩子的适配器边界用例、可归档对比的浏览器基准、与当前能力对齐的 README 特性清单。
|
|
24
|
+
- 一次大规模内部清理:全部运行时字符串字面量集中到 `utils/constants.ts` 并由之派生字面量类型,回放与去重从 `CrossTabDataBus` 拆分为自包含的 `ReplayManager` / `DedupManager`。
|
|
25
|
+
- demo 的「批量 10」publishBatch 按钮与 `/debug/wsstats` 帧计数及单帧 E2E,`asyncSink: true` 投递语义文档,以及与阻塞式发布消费者校验对齐的发布检查清单。
|
|
26
|
+
|
|
27
|
+
## 0.20.82 已完成范围
|
|
28
|
+
|
|
29
|
+
- E2E 默认断言上限提升至 20 秒;结构化克隆拒收(Symbol)与 cause 保留覆盖;共享模式会话生命周期经示例服务的连接数端点端到端验证。
|
|
30
|
+
|
|
31
|
+
## 0.20.81 已完成范围
|
|
32
|
+
|
|
33
|
+
- 浏览器基准新增 data-bus 热路径矩阵,健康摘要纳入 E2E 端到端断言,storage-event 通道与传输层批量进入 API 文档与能力矩阵。
|
|
34
|
+
|
|
35
|
+
## 0.20.80 已完成范围
|
|
36
|
+
|
|
37
|
+
- E2E 可靠性治理:失败 trace/视频与更长保留期、reload 类用例的先收敛后发布模式、符合文档保证的错峰突发模式,以及架构文档中的丢失与恢复矩阵。
|
|
38
|
+
|
|
39
|
+
## 0.20.79 已完成范围
|
|
40
|
+
|
|
41
|
+
- 已发布包消费自检成为 release 阻塞门禁(重试预算提升至 24 × 5 秒);丢失 ACK 交接的恢复链(TTL 清理 + 恢复后重选举)由回归固化。
|
|
42
|
+
|
|
43
|
+
## 0.20.78 已完成范围
|
|
44
|
+
|
|
45
|
+
- E2E 逐 Tab 断言真实 transport 后端;延迟关闭不变量由回归测试固化并写入架构文档;getting-started 覆盖健康摘要与协调降级。
|
|
46
|
+
|
|
47
|
+
## 0.20.77 已完成范围
|
|
48
|
+
|
|
49
|
+
- 修复无 factory 时静默降级本地会话的缺陷(打包的 Worker 现在真正被使用);补充默认后端与通道丢失恢复覆盖;demo 展示协调通道诊断与降级开关。
|
|
50
|
+
|
|
51
|
+
## 0.20.76 已完成范围
|
|
52
|
+
|
|
53
|
+
- 面向无 BroadcastChannel 环境的 opt-in storage-event 协调降级通道,含降级通道上的 owner 选举集成测试,并同步降级文档与能力矩阵。
|
|
54
|
+
|
|
55
|
+
## 0.20.75 已完成范围
|
|
56
|
+
|
|
57
|
+
- 单测套件新增热路径性能门禁(宽松阈值防灾难性退化,真实基准仍在 `pnpm bench`);IndexedDB replay 持久化新增脚本化故障注入,覆盖 invalidate 与恢复错误路径;审计确认 Release workflow 已集成已发布包消费自检。
|
|
58
|
+
|
|
59
|
+
## 0.20.74 已完成范围
|
|
60
|
+
|
|
61
|
+
- 可选的 `DataBusTransport.publishBatch`:WebSocket transport 单帧批量发送,demo server 支持批量帧,无批量能力的 transport 自动回退逐条发送;React/Vue 新增 `useCrossTabHealth` 绑定;健康判定纳入 transport 实时状态。
|
|
62
|
+
|
|
63
|
+
## 0.20.73 已完成范围
|
|
64
|
+
|
|
65
|
+
- IndexedDB replay 持久化适配器纳入单测(基于 `fake-indexeddb`):覆盖裁剪策略、批量分组、并发串行化、清理语义与瞬时打开失败恢复。
|
|
66
|
+
- 真实浏览器 E2E 新增三 Tab 并发发布突发与整连接重构建(stop/start)重入集群两个场景;architecture 文档新增稳定性不变量参考(中英文)。
|
|
67
|
+
|
|
68
|
+
## 0.20.72 已完成范围
|
|
69
|
+
|
|
70
|
+
- 扩展基准矩阵,覆盖 `publishBatch`、wildcard routing、dedup、replay prune、批量持久化与异步 trace sink。
|
|
71
|
+
- 长时稳定性加固:补齐 handoff ACK 世代校验、BFCache 往返、恢复耗尽重置、存储写退避恢复与 replay 持久化清理竞态的回归测试;修复反向的 stale-ACK 世代比较与批量 flush 复活清理历史两处缺陷。
|
|
72
|
+
- 生产能力:`getHealthSummary()` 就绪判定、`getPersistenceStats()`、diagnostics 中 transport 状态细化(status/suspended),以及构建时注入的 SDK 版本。
|
|
4
73
|
|
|
5
74
|
## 0.20.71 已完成范围
|
|
6
75
|
|
|
@@ -385,19 +454,31 @@
|
|
|
385
454
|
- publication metadata 做兼容性归一化:只接受非空 ID 与有限 timestamp。
|
|
386
455
|
- 补充 legacy、嵌套、fallback topic 和坏 metadata 协议夹具测试。
|
|
387
456
|
|
|
457
|
+
## 0.11.0 已完成范围
|
|
458
|
+
|
|
459
|
+
- 当持久化适配器支持 `clearBefore` 时,通过 `replay.retentionMs` 自动执行持久化回放留存。
|
|
460
|
+
- 周期性 trace 指标中加入去重接受/抑制计数。
|
|
461
|
+
- 覆盖 WebSocket、Centrifuge、Worker 边界与浏览器 E2E 的 publication metadata 兼容性测试。
|
|
462
|
+
- Service Worker transport 决策:在目标浏览器具备稳定的连接生命周期契约前,刻意保持不实现。
|
|
463
|
+
|
|
388
464
|
## 0.20.68 已交付
|
|
389
465
|
|
|
390
466
|
- 为集群帧和 worker snapshot 增加协议版本元数据,并保持旧版本缺失字段时的兼容处理。
|
|
391
467
|
|
|
392
468
|
## 0.20.69 候选
|
|
393
469
|
|
|
394
|
-
1.
|
|
395
|
-
2.
|
|
396
|
-
3.
|
|
397
|
-
4.
|
|
470
|
+
1. ~~增加 peer 能力矩阵,并在 diagnostics 暴露 SDK、后端与 transport 身份。~~ 已交付:`getDiagnostics()` 携带协议版本、未知消息统计、peer 协议版本与 transport 身份;`getHealthSummary()`/`getMetrics()` 现在也会随单一对象输出实时 trace 指标与 sink 状态。
|
|
471
|
+
2. ~~统一 replay、dedup、trace、recovery 与 cluster 健康指标。~~ 已交付:`getDiagnostics()` + `getMetrics()` + `getHealthSummary()` 在单一快照中覆盖生命周期、恢复、dedup、replay、持久化、协议、transport、cluster、trace 指标与 sink 背压。
|
|
472
|
+
3. ~~优化 IndexedDB 并发 append 与清理路径。~~ 已交付:相邻 `appendBatch` 变更合并为单事务;`clear`/`clearTopic`/`clearBefore` 顺序保持。
|
|
473
|
+
4. ~~增加 adaptive dedup、async trace、prune 和长时多 Tab 性能基线。~~ 部分交付:bench 覆盖负载加权评分、`getMetrics`、publishBatch 批次敏感性,以及既有 dedup/async-sink/persistence 用例。
|
|
398
474
|
|
|
399
475
|
## 0.13.0 候选
|
|
400
476
|
|
|
477
|
+
1. 冻结公共导出面与 transport 无关的 publication 信封。
|
|
478
|
+
2. 精确记录 at-least-once 投递与去重保证。
|
|
479
|
+
3. 增加长时浏览器浸泡覆盖:replay 留存、重连、BFCache 与 owner 迁移。
|
|
480
|
+
4. 为 1.0 前的协议别名发布迁移指南与弃用策略。
|
|
481
|
+
|
|
401
482
|
## 更长期候选
|
|
402
483
|
|
|
403
484
|
1. **Replay 生命周期与留存**:增加持久化 `clear`/`clearTopic`,退订/替换时清理旧历史,并通过 trace 与 error handler 暴露持久化失败;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cross-tab-worker-databus",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.85",
|
|
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",
|
|
@@ -24,9 +24,29 @@
|
|
|
24
24
|
],
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
|
-
"docs",
|
|
27
|
+
"docs/api.md",
|
|
28
|
+
"docs/architecture.md",
|
|
29
|
+
"docs/benchmarks.md",
|
|
30
|
+
"docs/capabilities.md",
|
|
31
|
+
"docs/configuration.md",
|
|
32
|
+
"docs/getting-started.md",
|
|
33
|
+
"docs/release-checklist.md",
|
|
34
|
+
"docs/roadmap.md",
|
|
35
|
+
"docs/transports.md",
|
|
36
|
+
"docs/README.md",
|
|
37
|
+
"docs/zh/api.md",
|
|
38
|
+
"docs/zh/architecture.md",
|
|
39
|
+
"docs/zh/benchmarks.md",
|
|
40
|
+
"docs/zh/capabilities.md",
|
|
41
|
+
"docs/zh/configuration.md",
|
|
42
|
+
"docs/zh/getting-started.md",
|
|
43
|
+
"docs/zh/release-checklist.md",
|
|
44
|
+
"docs/zh/roadmap.md",
|
|
45
|
+
"docs/zh/transports.md",
|
|
46
|
+
"docs/zh/README.md",
|
|
28
47
|
"CHANGELOG.md",
|
|
29
48
|
"README.md",
|
|
49
|
+
"README.zh.md",
|
|
30
50
|
"LICENSE"
|
|
31
51
|
],
|
|
32
52
|
"main": "./dist/cjs/index.cjs",
|
|
@@ -77,6 +97,8 @@
|
|
|
77
97
|
"test:coverage": "vitest run --coverage",
|
|
78
98
|
"bench": "vitest bench --run",
|
|
79
99
|
"bench:browser": "pnpm build && node scripts/bench-browser.mjs",
|
|
100
|
+
"bench:compare": "node scripts/bench-compare.mjs",
|
|
101
|
+
"bench:trend": "node scripts/bench-trend.mjs",
|
|
80
102
|
"verify:pack": "node scripts/verify-packed-consumer.mjs",
|
|
81
103
|
"verify:compat": "node scripts/verify-version-compat.mjs",
|
|
82
104
|
"verify:published": "node scripts/verify-published-consumer.mjs",
|
|
@@ -101,21 +123,22 @@
|
|
|
101
123
|
}
|
|
102
124
|
},
|
|
103
125
|
"devDependencies": {
|
|
104
|
-
"@eslint/js": "^
|
|
105
|
-
"@playwright/test": "^1.
|
|
126
|
+
"@eslint/js": "^10.0.1",
|
|
127
|
+
"@playwright/test": "^1.63.0",
|
|
106
128
|
"@testing-library/react": "^16.3.3",
|
|
107
|
-
"@types/node": "^
|
|
108
|
-
"@types/react": "^
|
|
109
|
-
"@vitest/coverage-v8": "^
|
|
110
|
-
"esbuild": "^0.
|
|
111
|
-
"eslint": "^
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"react
|
|
116
|
-
"
|
|
117
|
-
"typescript
|
|
118
|
-
"
|
|
129
|
+
"@types/node": "^26.5.0",
|
|
130
|
+
"@types/react": "^19.3.0",
|
|
131
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
132
|
+
"esbuild": "^0.28.2",
|
|
133
|
+
"eslint": "^10.10.0",
|
|
134
|
+
"fake-indexeddb": "^6.2.5",
|
|
135
|
+
"globals": "^17.12.0",
|
|
136
|
+
"jsdom": "^30.0.1",
|
|
137
|
+
"react": "^19.3.0",
|
|
138
|
+
"react-dom": "^19.3.0",
|
|
139
|
+
"typescript": "^6.0.3",
|
|
140
|
+
"typescript-eslint": "^8.70.0",
|
|
141
|
+
"vitest": "^5.0.0",
|
|
119
142
|
"vue": "^3.5.42"
|
|
120
143
|
},
|
|
121
144
|
"engines": {
|