cross-tab-worker-databus 0.21.56 → 0.21.58
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 +41 -0
- package/dist/centrifuge.js +1 -1
- package/dist/{chunk-VDCLCCMN.js → chunk-X33QQUTG.js} +117 -23
- package/dist/chunk-X33QQUTG.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +116 -22
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/index.cjs +116 -22
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/core/cluster.d.ts +64 -3
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/environment.d.ts +23 -1
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/docs/api.md +3 -1
- package/docs/architecture.md +18 -16
- package/docs/benchmarks.md +8 -8
- package/docs/configuration.md +2 -2
- package/docs/roadmap.md +1 -1
- package/docs/zh/api.md +3 -1
- package/docs/zh/architecture.md +15 -13
- package/docs/zh/benchmarks.md +8 -8
- package/docs/zh/configuration.md +2 -2
- package/docs/zh/roadmap.md +1 -1
- package/package.json +7 -7
- package/dist/chunk-VDCLCCMN.js.map +0 -7
package/dist/core/cluster.d.ts
CHANGED
|
@@ -204,7 +204,7 @@ export declare class WorkerClusterRuntime {
|
|
|
204
204
|
* subscribers remain, deletes the route so the owning Worker can unsubscribe.
|
|
205
205
|
*/
|
|
206
206
|
unsubscribe(topic: string): void;
|
|
207
|
-
/** Remove this
|
|
207
|
+
/** Remove this Runtime's subscriber record and, when it was the last one, delete
|
|
208
208
|
* the route. Returns the topicKey (so callers like `unsubscribe` can reuse
|
|
209
209
|
* it instead of re-hashing the topic to evict the reverse cache). */
|
|
210
210
|
private releaseSubscription;
|
|
@@ -363,10 +363,60 @@ export declare class WorkerClusterRuntime {
|
|
|
363
363
|
private sendControl;
|
|
364
364
|
/** Post a message on the BroadcastChannel. Returns false on postMessage failure. */
|
|
365
365
|
private send;
|
|
366
|
+
/**
|
|
367
|
+
* Whether any other live Worker record already carries `tabId`.
|
|
368
|
+
*
|
|
369
|
+
* Used once per document, from the constructor, to tell a browser-duplicated
|
|
370
|
+
* tab from this tab's own refresh: the copy inherits `sessionStorage` but not
|
|
371
|
+
* the opener, so the identity stored there is the only shared state and the
|
|
372
|
+
* Worker records are the only evidence that another live document holds it.
|
|
373
|
+
* Liveness is the same heartbeat window `readWorkers()` prunes by, so a record
|
|
374
|
+
* left behind by an abnormal exit is reported as live until it expires — the
|
|
375
|
+
* only false positive, and it re-mints one identity instead of letting two
|
|
376
|
+
* live tabs share one.
|
|
377
|
+
*
|
|
378
|
+
* The `!this.storage` leg is the degraded mode, and it earns its line for two
|
|
379
|
+
* reasons rather than one. It is what narrows the field for the scan below
|
|
380
|
+
* (`StorageLike | null` is rejected by `readAllByPrefix`), so the compiler
|
|
381
|
+
* holds it; and it is *not* what decides the verdict, because `listKeys()`
|
|
382
|
+
* catches its own failure and returns no records either way — measured by
|
|
383
|
+
* emptying this consequent, which leaves the suite green. What the inverted
|
|
384
|
+
* return does prove is the behaviour, not the deletion: returning `true` here
|
|
385
|
+
* fails 'keeps the inherited id when there is no storage to probe', since
|
|
386
|
+
* without `localStorage` there is no second document to collide with.
|
|
387
|
+
*/
|
|
388
|
+
private isTabIdLiveElsewhere;
|
|
366
389
|
/** Read all live worker records from storage, pruning stale entries past the TTL. */
|
|
367
390
|
private readWorkers;
|
|
368
391
|
/** Enumerate all tab IDs that have a subscriber record for `topicKey`. */
|
|
369
392
|
private readSubscriberTabIds;
|
|
393
|
+
/**
|
|
394
|
+
* One scan of `topicKey`'s subscriber records, answering the two questions
|
|
395
|
+
* callers ask: which Tabs hold a subscription (emptiness checks, orphan-route
|
|
396
|
+
* pruning) and which **Runtimes** do (the stranded-handoff re-election).
|
|
397
|
+
*
|
|
398
|
+
* The second answer is the finer one and the reason this is one method rather
|
|
399
|
+
* than two scans: a tab-level answer lets a leftover record from a sibling
|
|
400
|
+
* Runtime speak for a Worker that never subscribed to the topic, and standing
|
|
401
|
+
* down on that proof stalls the recovery forever (see the call site).
|
|
402
|
+
*
|
|
403
|
+
* A legacy record — written before records carried `workerId` — proves only
|
|
404
|
+
* that *some* Runtime in its tab subscribes, so it contributes to the tab set
|
|
405
|
+
* and **not** to the worker set. Treating it as the whole tab, which is what
|
|
406
|
+
* the tab-level reader effectively did, is the conservative-looking choice
|
|
407
|
+
* that can stall; the cost of the other direction is one redundant
|
|
408
|
+
* `CONTROL/SUBSCRIBE` to a peer that is about to confirm anyway.
|
|
409
|
+
*/
|
|
410
|
+
private readSubscriberIds;
|
|
411
|
+
/** Whether a subscriber record still belongs to a live Runtime.
|
|
412
|
+
*
|
|
413
|
+
* A record written by this version names its `workerId`, so liveness is the
|
|
414
|
+
* Worker set the reconcile pass already prunes by — which is what keeps two
|
|
415
|
+
* Runtimes in one tab independent. A record from an older version carries no
|
|
416
|
+
* `workerId`; it is honoured while its *tab* lives, the finest identity it
|
|
417
|
+
* has, and each Runtime replaces its own with a worker-keyed record on its
|
|
418
|
+
* next write. */
|
|
419
|
+
private isSubscriberRecordLive;
|
|
370
420
|
/** Read the current route for `topicKey`. With a storage layer this returns
|
|
371
421
|
* the durable route, or null when none is recorded. Without one (degraded
|
|
372
422
|
* mode) it returns the synthesized local route from `buildLocalRoute`, which
|
|
@@ -387,9 +437,19 @@ export declare class WorkerClusterRuntime {
|
|
|
387
437
|
private confirmRoute;
|
|
388
438
|
/** Remove routes whose topic has no subscribers and whose TTL has expired. */
|
|
389
439
|
private cleanupOrphanedRoutes;
|
|
390
|
-
/** Remove subscriber records
|
|
440
|
+
/** Remove subscriber records whose owning Runtime (or, for a legacy record,
|
|
441
|
+
* whose tab) is no longer active. */
|
|
391
442
|
private cleanupOrphanedSubscribers;
|
|
392
|
-
/** Persist a subscriber record for this
|
|
443
|
+
/** Persist a subscriber record for this Runtime on `topicKey`.
|
|
444
|
+
*
|
|
445
|
+
* Keyed by `workerId`, not `tabId`. A document may run several Runtimes that
|
|
446
|
+
* share one `tabId` on purpose (the market + notice pattern), and a tab-keyed
|
|
447
|
+
* record belonged to all of them at once: whichever unsubscribed first deleted
|
|
448
|
+
* the others' intent, the route then looked orphaned, and the owner dropped a
|
|
449
|
+
* transport subscription its surviving sibling still needed — a delivery gap
|
|
450
|
+
* until that sibling's next reconcile tick re-elected an owner. Duplicated
|
|
451
|
+
* tabs get the same protection even when the identity probe cannot see them,
|
|
452
|
+
* which is why the fix is here as well as in `isTabIdLiveElsewhere()`. */
|
|
393
453
|
private writeSubscriber;
|
|
394
454
|
/** Persist the current worker record with an updated heartbeat timestamp.
|
|
395
455
|
* @param notify — when true, broadcast a REGISTRY nudge so peers reconcile
|
|
@@ -424,6 +484,7 @@ export declare class WorkerClusterRuntime {
|
|
|
424
484
|
private rememberTopic;
|
|
425
485
|
private workerStorageKey;
|
|
426
486
|
private routeStorageKey;
|
|
487
|
+
/** `ownerId` is the Runtime's `workerId`; older versions used the `tabId`. */
|
|
427
488
|
private subscriberStorageKey;
|
|
428
489
|
private removeStorage;
|
|
429
490
|
/** Force-flush any pending batched writes (used during shutdown/teardown). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -135,6 +135,28 @@ export declare function canUseStorage(storage: StorageLike | null, probeKey: str
|
|
|
135
135
|
* sessionStorage is scoped to the tab and survives refresh, so the same tab
|
|
136
136
|
* retains its identity across the page lifecycle without coordination overhead.
|
|
137
137
|
* Falls back to a random ID when sessionStorage is unavailable.
|
|
138
|
+
*
|
|
139
|
+
* A stored value is inherited by two different kinds of new document, and only
|
|
140
|
+
* one of them should keep it. A refresh (or a session restore) re-enters the
|
|
141
|
+
* *same* tab: nothing else is using the value, so it is reused. A tab the
|
|
142
|
+
* browser opened or duplicated is a *second* live document holding a copy, and
|
|
143
|
+
* two of them must not present one identity. The coordination plane does not
|
|
144
|
+
* distinguish them by subscriber *keys* (those are per Runtime, see
|
|
145
|
+
* `writeSubscriber()`), so a shared id does not lose a subscription — it makes
|
|
146
|
+
* a false one: the public snapshot, the diagnostics and the tab-level
|
|
147
|
+
* subscriber aggregation all report two documents as one.
|
|
148
|
+
*
|
|
149
|
+
* `window.open()` is visible (`window.opener`), but the browser's own
|
|
150
|
+
* "Duplicate tab" is not: it copies sessionStorage with no opener at all. That
|
|
151
|
+
* half needs evidence from outside the document, which `options` supplies; the
|
|
152
|
+
* caller's probe is consulted only on a document's first lookup, because later
|
|
153
|
+
* runtimes in the same document must keep the identity this document was issued
|
|
154
|
+
* (see `tabIdentityInitialized`).
|
|
138
155
|
*/
|
|
139
|
-
export declare function getOrCreateTabId(environment: ClusterEnvironment, key?: string
|
|
156
|
+
export declare function getOrCreateTabId(environment: ClusterEnvironment, key?: string, options?: {
|
|
157
|
+
/** Reports whether another live document already uses the inherited value.
|
|
158
|
+
* The cluster answers from its Worker records, which a duplicated tab cannot
|
|
159
|
+
* copy: they live in `localStorage` under a random `workerId`. */
|
|
160
|
+
isIdentityClaimedByPeer?: (candidate: string) => boolean;
|
|
161
|
+
}): string;
|
|
140
162
|
//# sourceMappingURL=environment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"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"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -140,6 +140,13 @@ export interface WorkerRoute {
|
|
|
140
140
|
export interface TopicSubscriberRecord {
|
|
141
141
|
/** The tab that holds this subscription. */
|
|
142
142
|
tabId: string;
|
|
143
|
+
/** The Runtime that holds it. A document may run several (the market +
|
|
144
|
+
* notice pattern), and they share one `tabId` on purpose — so a record keyed
|
|
145
|
+
* and pruned by `tabId` alone is owned by all of them at once, and the first
|
|
146
|
+
* one to unsubscribe deletes the others' intent. Optional because records
|
|
147
|
+
* written before this field existed are still honoured while their tab
|
|
148
|
+
* lives. */
|
|
149
|
+
workerId?: string;
|
|
143
150
|
/** Timestamp (ms) of the last subscriber write. */
|
|
144
151
|
updatedAt: number;
|
|
145
152
|
}
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
package/docs/api.md
CHANGED
|
@@ -493,12 +493,14 @@ Generates a stable 128-bit hexadecimal opaque key. Used to avoid writing raw con
|
|
|
493
493
|
|
|
494
494
|
Creates a default browser environment adapter, including storage, BroadcastChannel, timers, and page lifecycle events.
|
|
495
495
|
|
|
496
|
-
### `getOrCreateTabId(environment, key?)`
|
|
496
|
+
### `getOrCreateTabId(environment, key?, options?)`
|
|
497
497
|
|
|
498
498
|
Returns the stable identity of the current page/tab instance, reading it from session storage and creating one (`tab-<random>`) on first call, so a reloaded tab reclaims its routes instead of looking like a brand new one.
|
|
499
499
|
|
|
500
500
|
The stored value is deliberately *not* reused when `window.opener` is present: `window.open()` clones the opener's `sessionStorage` into the child, so a blind reuse would make two live tabs share one identity. When storage is unavailable or throws, a fresh ID is generated instead.
|
|
501
501
|
|
|
502
|
+
The browser's own **Duplicate tab** copies `sessionStorage` too, and gives the copy *no* opener, so the opener check cannot see it. `options.isIdentityClaimedByPeer(candidate)` is the caller's evidence for that case: `WorkerClusterRuntime` answers it from this cluster's live Worker records, and a heartbeat-live record carrying the inherited value makes the duplicate take a fresh ID (persisted, so later Runtimes in the same document share it). The probe runs on a document's first lookup only, and never when an opener already settled the question — a refresh removes and flushes its own Worker record, so it keeps its identity; after an abnormal exit the stale record lives for up to `workerTtlMs`, and a reload inside that window takes a fresh ID instead.
|
|
503
|
+
|
|
502
504
|
### `selectWorkerBackend(mode, availability?)`
|
|
503
505
|
|
|
504
506
|
Selects the actual backend based on `WorkerMode` and capability detection, returning `'shared' | 'dedicated' | 'local'`:
|
package/docs/architecture.md
CHANGED
|
@@ -108,10 +108,10 @@ BroadcastChannel messages carry topic names, event types, and publication payloa
|
|
|
108
108
|
```text
|
|
109
109
|
cross-tab-worker-databus:{clusterHash}:worker:{workerId}
|
|
110
110
|
cross-tab-worker-databus:{clusterHash}:route:{topicKey}
|
|
111
|
-
cross-tab-worker-databus:{clusterHash}:subscriber:{topicKey}:{
|
|
111
|
+
cross-tab-worker-databus:{clusterHash}:subscriber:{topicKey}:{workerId}
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
Unlike the old single-JSON route table, subscribers use
|
|
114
|
+
Unlike the old single-JSON route table, subscribers use one independent key per *Runtime* — the `workerId`, not the `tabId`, because a document may run several Runtimes that share one tab. When Tab A and Tab B subscribe/unsubscribe concurrently, they do not perform a read-modify-write on the same `subscribers[]`, structurally reducing the probability of lost updates; and when one of two Runtimes in the *same* tab unsubscribes, only its own record goes, so the sibling's route and transport subscription survive.
|
|
115
115
|
|
|
116
116
|
### Worker Record
|
|
117
117
|
|
|
@@ -217,7 +217,7 @@ topic
|
|
|
217
217
|
└─ createOpaqueKey(topic) → topicKey
|
|
218
218
|
├─ route:{topicKey}
|
|
219
219
|
│ └─ workerId / tabId / generation / confirmedAt
|
|
220
|
-
└─ subscriber:{topicKey}:{
|
|
220
|
+
└─ subscriber:{topicKey}:{workerId}
|
|
221
221
|
|
|
222
222
|
BroadcastChannel CONTROL
|
|
223
223
|
└─ topic + topicKey + sourceWorkerId + targetWorkerId + action
|
|
@@ -288,7 +288,7 @@ sequenceDiagram
|
|
|
288
288
|
|
|
289
289
|
App->>RuntimeA: subscribe(topic, handler)
|
|
290
290
|
RuntimeA->>RuntimeA: derive topicKey
|
|
291
|
-
RuntimeA->>Storage: write subscriber:{topicKey}:{
|
|
291
|
+
RuntimeA->>Storage: write subscriber:{topicKey}:{workerId}
|
|
292
292
|
RuntimeA->>Storage: read or create route:{topicKey}
|
|
293
293
|
RuntimeA->>Channel: CONTROL/SUBSCRIBE(topic, topicKey, targetWorkerId)
|
|
294
294
|
Channel->>RuntimeB: deliver control message
|
|
@@ -300,7 +300,7 @@ sequenceDiagram
|
|
|
300
300
|
RuntimeA->>App: invoke handler(payload)
|
|
301
301
|
```
|
|
302
302
|
|
|
303
|
-
A second Tab subscribing to the same Topic adds only its own subscriber record; it does not create another transport subscription while the existing owner is alive. Unsubscribe removes the current
|
|
303
|
+
A second Tab subscribing to the same Topic adds only its own subscriber record; it does not create another transport subscription while the existing owner is alive. Unsubscribe removes the current Runtime's subscriber record and, when that was the last one, the same Runtime deletes the route and sends `CONTROL/UNSUBSCRIBE` to the worker the route named, which then drops its assignment and releases the transport subscription.
|
|
304
304
|
|
|
305
305
|
### Console diagnostics
|
|
306
306
|
|
|
@@ -350,7 +350,7 @@ Every keyed piece of state in the system — the full picture of what the previo
|
|
|
350
350
|
| `knownTopics` | `WorkerClusterRuntime` | `topicKey` | Plaintext `topic` | FIFO scan capped at 500 that skips owned keys and the key being remembered, so an all-owned cache lets the cap slip | The reverse-lookup cache; also the only source of plaintext in storage-less mode |
|
|
351
351
|
| Storage `worker:` | persisted | `clusterHash:…:worker:{workerId}` | JSON `WorkerRecord` | Heartbeat refresh; pruned after `workerTtlMs` | Cross-tab liveness discovery |
|
|
352
352
|
| Storage `route:` | persisted | `clusterHash:…:route:{topicKey}` | JSON `WorkerRoute` | Created/stamped by subscriber; pruned when no subscribers + TTL expired | Cross-tab owner mapping |
|
|
353
|
-
| Storage `subscriber:` | persisted | `clusterHash:…:subscriber:{topicKey}:{
|
|
353
|
+
| Storage `subscriber:` | persisted | `clusterHash:…:subscriber:{topicKey}:{workerId}` | JSON `TopicSubscriberRecord` | Written per Runtime subscription; pruned when that Runtime dies (a legacy tab-keyed record is pruned with its Tab) | Cross-tab subscriber intent |
|
|
354
354
|
|
|
355
355
|
**How the three in-memory topic forms relate** (`knownTopics` ↔ `assignedTopics` ↔ the four plaintext sets):
|
|
356
356
|
|
|
@@ -394,7 +394,7 @@ The owning Worker filters every publication it receives with `isAssigned(topic)`
|
|
|
394
394
|
2. If a visible Tab exists, visible Workers are preferred when choosing an owner for a new Topic; when all Tabs are hidden, hidden Workers remain eligible.
|
|
395
395
|
3. Sorted by `registeredAt, workerId`, up to 3 active Workers are selected as new-route candidates.
|
|
396
396
|
4. An existing route remains sticky as long as its owner Worker record is alive, regardless of load, visibility, or whether the owner remains in the new-route candidate set.
|
|
397
|
-
5. A second Tab subscribing to an existing Topic only writes its subscriber record. It does not modify the route or call
|
|
397
|
+
5. A second Tab — or a second Runtime in the same Tab — subscribing to an existing Topic only writes its own subscriber record. It does not modify the route or call a transport `subscribe`.
|
|
398
398
|
6. Only a Topic without a route, or a route whose owner has departed or expired by heartbeat TTL, is assigned to the least-loaded candidate Worker.
|
|
399
399
|
7. A new route is considered unconfirmed until the owner writes `confirmedAt`; the subscriber will automatically resend the control message.
|
|
400
400
|
|
|
@@ -450,7 +450,7 @@ sequenceDiagram
|
|
|
450
450
|
|
|
451
451
|
App->>Bus: subscribe(topic, handler)
|
|
452
452
|
Bus->>Bus: First handler in this Tab?
|
|
453
|
-
Bus->>Route: Write subscriber:{topicKey}:{
|
|
453
|
+
Bus->>Route: Write subscriber:{topicKey}:{workerId}
|
|
454
454
|
Route-->>Bus: Current owner
|
|
455
455
|
alt Owner does not exist or is invalid
|
|
456
456
|
Bus->>Route: Write lowest-load owner
|
|
@@ -478,7 +478,7 @@ The system maintains four independent subscription-tracking sets. Understanding
|
|
|
478
478
|
Application: subscribe(topic, handler)
|
|
479
479
|
→ topicHandlers 0→1
|
|
480
480
|
→ cluster.subscribe(topic) → subscribedTopics.add(topic)
|
|
481
|
-
→ write subscriber:{topicKey}:{
|
|
481
|
+
→ write subscriber:{topicKey}:{workerId}
|
|
482
482
|
→ readRoute(topicKey)
|
|
483
483
|
→ if no route: selectLeastLoadedWorker, writeRoute, sendControl(SUBSCRIBE)
|
|
484
484
|
→ owner receives CONTROL/SUBSCRIBE
|
|
@@ -514,7 +514,7 @@ A publication travels publisher → current Topic owner → transport/server →
|
|
|
514
514
|
2. The owner runs `transport.publish(topic, data)`. Because only the owner holds a real transport subscription to the topic, the server delivers the resulting publication back to exactly one Worker.
|
|
515
515
|
3. The owner accepts a publication only while `isAssigned(topic)` still holds. Stale messages from an expired owner are discarded — keeping the fan-out single-sourced.
|
|
516
516
|
4. The owner broadcasts `EVENT/DATABUS_PUBLICATION` over the BroadcastChannel and, if its own Tab also has a local subscription, dispatches once directly. BroadcastChannel never echoes to the sender, so there is no duplicate dispatch.
|
|
517
|
-
5. Every other Tab receives the `EVENT` but invokes its local handlers only when
|
|
517
|
+
5. Every other Tab receives the `EVENT` but invokes its local handlers only when its own subscription intent covers that topic — the gate reads the in-memory subscription set, while the `subscriber:{topicKey}:{workerId}` record is what tells peers that intent exists; Tabs without a local subscription drop the message.
|
|
518
518
|
|
|
519
519
|
Optional publication metadata (`messageId` and `timestamp`) follows the same path as the payload: `CONTROL/PUBLISH` → transport/server → `DataBusMessage` → `EVENT` fan-out. It is never written to coordination storage. Transports normalize legacy payloads and the canonical `DataBusPublicationEnvelope` before the three dispatch gates.
|
|
520
520
|
|
|
@@ -562,7 +562,7 @@ After the optional `messageId` deduplication gate, every accepted publication fr
|
|
|
562
562
|
|
|
563
563
|
2. **`broadcastEvent('DATABUS_PUBLICATION', message)`** — called only after `isAssigned` passes. The owning Worker fans the message out to all tabs via BroadcastChannel `EVENT`. Each tab receives the event but does not dispatch yet — it must pass the inner gate.
|
|
564
564
|
|
|
565
|
-
3. **`hasLocalSubscriber(topic)`** — called on each tab receiving the `EVENT`.
|
|
565
|
+
3. **`hasLocalSubscriber(topic)`** — called on each tab receiving the `EVENT`. It reads the in-memory subscription set (including wildcard patterns), not the durable subscriber record; only tabs whose own subscription covers this topic invoke the registered handler. Tabs without a local subscription drop the message silently.
|
|
566
566
|
|
|
567
567
|
These three checks provide **at-most-once fan-out per accepted transport publication**:
|
|
568
568
|
- The outer gate (`isAssigned`) prevents duplicate broadcasts from a stale owner.
|
|
@@ -583,8 +583,8 @@ Transport message → isAssigned(topic)? → Yes → broadcastEvent(EVENT)
|
|
|
583
583
|
|
|
584
584
|
Cluster convergence is driven on two timelines:
|
|
585
585
|
|
|
586
|
-
- **Heartbeat + reconcile loop** (default `3000 ms`, `heartbeatIntervalMs`). On every tick each Worker refreshes its own record and runs a reconcile pass: prunes Workers past `workerTtlMs`, orphaned subscribers whose Tab is no longer active, and orphaned routes that have no subscribers and exceed the TTL; repairs a confirmed route that names this Worker after its assignment was cleared (see the invariant below); recomputes its own active/standby role; re-writes its subscriber records; and re-sends `CONTROL/SUBSCRIBE` for any route that still lacks `confirmedAt` — which also recovers control messages lost on the channel.
|
|
587
|
-
- **`REGISTRY` nudge**. Writes to Worker records and routes broadcast a `REGISTRY` message so every peer reconciles immediately rather than waiting for the next heartbeat. A subscriber-only write does not: `subscribe()` on a topic whose owner is still live writes this
|
|
586
|
+
- **Heartbeat + reconcile loop** (default `3000 ms`, `heartbeatIntervalMs`). On every tick each Worker refreshes its own record and runs a reconcile pass: prunes Workers past `workerTtlMs`, orphaned subscribers whose Runtime (or, for a legacy record, whose Tab) is no longer active, and orphaned routes that have no subscribers and exceed the TTL; repairs a confirmed route that names this Worker after its assignment was cleared (see the invariant below); recomputes its own active/standby role; re-writes its subscriber records; and re-sends `CONTROL/SUBSCRIBE` for any route that still lacks `confirmedAt` — which also recovers control messages lost on the channel.
|
|
587
|
+
- **`REGISTRY` nudge**. Writes to Worker records and routes broadcast a `REGISTRY` message so every peer reconciles immediately rather than waiting for the next heartbeat. A subscriber-only write does not: `subscribe()` on a topic whose owner is still live writes this Runtime's subscriber record and returns.
|
|
588
588
|
|
|
589
589
|
Heartbeat writes are not announced, so a stale record is only noticed within one heartbeat interval. The worst case for failing to detect a dead owner is `heartbeatIntervalMs + workerTtlMs` (default about 13 s); see [TTL Message-Loss Window](./configuration.md#ttl-message-loss-window) for the trade-offs.
|
|
590
590
|
|
|
@@ -592,11 +592,13 @@ Heartbeat writes are not announced, so a stale record is only noticed within one
|
|
|
592
592
|
|
|
593
593
|
On normal close or entry into BFCache, `pagehide` pauses the Runtime: it deletes Worker and subscriber records, yields the actual owner, and closes the underlying transport, but retains the business subscription intent in memory. After the page is restored via `pageshow`, DataBus rebuilds the Worker/connection, and the Runtime automatically re-registers, restores subscriber records, and reconciles Topics, without requiring the business to re-call `subscribe`.
|
|
594
594
|
|
|
595
|
-
#### Tab identity
|
|
595
|
+
#### Tab identity: refreshes, `window.open`, and duplicated tabs
|
|
596
596
|
|
|
597
|
-
Each Runtime stores its `tabId` in `sessionStorage` so refreshes retain identity; every Runtime gets a random-suffixed `workerId`.
|
|
597
|
+
Each Runtime stores its `tabId` in `sessionStorage` so refreshes retain identity; every Runtime gets a random-suffixed `workerId`. Two kinds of new document inherit that stored value, and only one of them may keep it. A refresh re-enters the *same* tab, so the value is unclaimed and is reused. A browser-duplicated tab (`window.open()`, or the browser's own Duplicate tab) is a *second* live document holding a copy, and two of them must not present one identity: `tabId` is the identity the public snapshot reports and one half of the key the diagnostic records use, so a copy would speak for the original. (Subscriber records are keyed per Runtime, so the coordination plane no longer *depends* on that uniqueness — the guard exists so that the identity itself is true.)
|
|
598
598
|
|
|
599
|
-
|
|
599
|
+
The two sources of evidence are different in kind. `window.open()` is visible as `window.opener`, so the SDK discards a copied `sessionStorage` id when an opener is present and generates a fresh one; applications are still encouraged to use `noopener`. The browser's Duplicate tab carries no opener at all, so the SDK probes this cluster's Worker records instead — they live in `localStorage` under a random `workerId` and cannot be copied with the session. A heartbeat-live record carrying the inherited id means another live document is using it, and the duplicate mints a fresh id that is persisted for later Runtimes in the same document.
|
|
600
|
+
|
|
601
|
+
That probe runs once per document, from the constructor. A refresh is recognised because `pause()` removes the departing document's Worker record and flushes that removal before the page goes away; after an abnormal exit the record survives for up to `workerTtlMs`, so a reload inside that window takes a fresh id (the stale record is then pruned by the normal TTL path). Inspection records are keyed by `tabId + workerId`, preventing Worker restart or handoff snapshots from overwriting one another.
|
|
600
602
|
|
|
601
603
|
`visibilitychange` does not remove business subscriptions or migrate established routes. A hidden Tab keeps the Topics it already owns and can still receive data broadcast by other owners. Visibility only affects candidate selection when a new Topic needs its first owner.
|
|
602
604
|
|
package/docs/benchmarks.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
# Browser Benchmark Trend
|
|
4
4
|
|
|
5
|
-
> Data through 2026-10-
|
|
5
|
+
> Data through 2026-10-30, from the 97 archived `bench-results/browser-*.json` reports (run `pnpm bench:browser` to add one; regenerate this doc with `node scripts/bench-trend.mjs`).
|
|
6
6
|
|
|
7
7
|
The comparison baseline for release gating is `pnpm bench:compare --fail-above-pct 50`, which compares the newest report against the median of the same metric in the preceding reports *and* requires the new value to exceed the highest of those samples (50% ceiling absorbs shared-runner noise; a single previous report was a fragile baseline because the in-page hot-path metrics alternate between a fast and a slow mode on identical code — and a median over an alternating sample is only stable while the modes are mixed, so a percentage alone can still fail on nothing but a mode shift. Metrics excused by that second leg are listed as "within-baseline, not gated" rather than passing silently). This doc records the long-run picture: values are per-metric latencies where lower is better, and the last column is the best run inside the most recent 5 reports — not an all-time record, because the in-page matrix changed measurement semantics in early September 2026 and older reports are not comparable.
|
|
8
8
|
|
|
9
9
|
<!-- BENCH-TREND:BEGIN (machine-generated table) -->
|
|
10
10
|
| Metric | Previous (ms) | Latest (ms) | Δ | Best of last 5 runs (ms) |
|
|
11
11
|
|---|---|---|---|---|
|
|
12
|
-
| publish per-message (ms, lower is better) — dedicated |
|
|
13
|
-
| publish per-message (ms, lower is better) — shared |
|
|
14
|
-
| wildcard dispatch ×1000 (ms, lower is better) |
|
|
15
|
-
| publishBatch ×1000 (ms, lower is better) |
|
|
16
|
-
| dedup ×1000 (ms, lower is better) |
|
|
17
|
-
| trace + publish ×1000 (ms, lower is better) | 5.
|
|
18
|
-
| first-packet cold dispatch (ms, lower is better) | 0 | 0 | +0.
|
|
12
|
+
| publish per-message (ms, lower is better) — dedicated | 39.1206 | 37.9266 | -1.19 | 37.9266 |
|
|
13
|
+
| publish per-message (ms, lower is better) — shared | 34.1177 | 34.5476 | +0.43 | 33.8229 |
|
|
14
|
+
| wildcard dispatch ×1000 (ms, lower is better) | 6.7 | 6.9 | +0.20 | 6 |
|
|
15
|
+
| publishBatch ×1000 (ms, lower is better) | 4.3 | 4.1 | -0.20 | 3.9 |
|
|
16
|
+
| dedup ×1000 (ms, lower is better) | 16.1 | 16.7 | +0.60 | 13.2 |
|
|
17
|
+
| trace + publish ×1000 (ms, lower is better) | 5.4 | 5.1 | -0.30 | 5.1 |
|
|
18
|
+
| first-packet cold dispatch (ms, lower is better) | 0 | 0.1 | +0.10 | 0 |
|
|
19
19
|
<!-- BENCH-TREND:END -->
|
|
20
20
|
|
|
21
21
|
Notes:
|
package/docs/configuration.md
CHANGED
|
@@ -273,11 +273,11 @@ When non-clonable data is passed, `CentrifugeWorkerTransport` will throw a clear
|
|
|
273
273
|
|
|
274
274
|
## Storage Data Boundaries
|
|
275
275
|
|
|
276
|
-
The coordination records this library writes itself — `{clusterHash}:worker:{workerId}`, `{clusterHash}:route:{topicKey}`, `{clusterHash}:subscriber:{topicKey}:{
|
|
276
|
+
The coordination records this library writes itself — `{clusterHash}:worker:{workerId}`, `{clusterHash}:route:{topicKey}`, `{clusterHash}:subscriber:{topicKey}:{workerId}`, and the tab-id key — hold only:
|
|
277
277
|
|
|
278
278
|
- Worker and Tab identity, role, status, visibility, the owned-topic `load` figure, an optional rolling throughput sample, the advertised protocol version, and the heartbeat / first-registration timestamps
|
|
279
279
|
- The opaque Topic key, its owner's Worker and Tab identity, the last-update and generation numbers, and — during a graceful handoff — the previous owner and the owner's confirmation timestamp
|
|
280
|
-
- A subscriber record's Tab ID and its last-update timestamp
|
|
280
|
+
- A subscriber record's Tab ID, the Runtime's Worker ID (absent in a record written by an older version), and its last-update timestamp
|
|
281
281
|
- The tab's own persisted id, which is what lets a reload reclaim its routes — written to `sessionStorage`, not to the cluster's `localStorage` namespace
|
|
282
282
|
|
|
283
283
|
Those records never hold:
|
package/docs/roadmap.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
-
0.21.
|
|
3
|
+
0.21.57 was released on October 30, 2026. The project is intentionally continuing through reliability-focused releases before a 1.0.0 stability freeze.
|
|
4
4
|
|
|
5
5
|
## 0.21.44 delivered scope
|
|
6
6
|
|
package/docs/zh/api.md
CHANGED
|
@@ -492,12 +492,14 @@ useVueCrossTabSubscription(bus, 'chat.*', message => console.log(message.data));
|
|
|
492
492
|
|
|
493
493
|
创建默认浏览器环境适配器,包含 storage、BroadcastChannel、定时器和页面生命周期事件。
|
|
494
494
|
|
|
495
|
-
### `getOrCreateTabId(environment, key?)`
|
|
495
|
+
### `getOrCreateTabId(environment, key?, options?)`
|
|
496
496
|
|
|
497
497
|
返回当前页面/标签页实例的稳定标识:优先从 sessionStorage 读取,首次调用时创建(`tab-<random>`)并写回,因此刷新后的标签页会认领原有 route,而不是被当成一个全新标签页。
|
|
498
498
|
|
|
499
499
|
存在 `window.opener` 时**刻意不**复用已存储的值:`window.open()` 会把 opener 的 `sessionStorage` 克隆给子页面,盲目复用会让两个存活的标签页共用一个身份。storage 不可用或抛错时改为生成新 ID。
|
|
500
500
|
|
|
501
|
+
浏览器自带的**复制标签页(Duplicate tab)**同样会复制 `sessionStorage`,而且复制出来的页面**没有** opener,因此 opener 检查看不到它。`options.isIdentityClaimedByPeer(candidate)` 就是调用方对这一情形的证据:`WorkerClusterRuntime` 用本集群存活的 Worker 记录来回答,若存在一条心跳仍新鲜、且带着被继承 id 的记录,复制出的标签页就改领一个新 ID(并写回,同一 document 内后续 Runtime 共用)。该探测只在一个 document 的首次查找时执行,opener 已给出结论时也不执行——刷新会在 `pause()` 里删除并 flush 自己的 Worker 记录,因此保留原身份;异常退出留下的记录会存活至多一个 `workerTtlMs`,在这个窗口内刷新则会领到新 ID。
|
|
502
|
+
|
|
501
503
|
### `selectWorkerBackend(mode, availability?)`
|
|
502
504
|
|
|
503
505
|
按 `WorkerMode` 和能力检测选择实际后端,返回 `'shared' | 'dedicated' | 'local'`:
|
package/docs/zh/architecture.md
CHANGED
|
@@ -98,10 +98,10 @@ BroadcastChannel 消息以明文传输 Topic 名称、事件类型和 publicatio
|
|
|
98
98
|
```text
|
|
99
99
|
cross-tab-worker-databus:{clusterHash}:worker:{workerId}
|
|
100
100
|
cross-tab-worker-databus:{clusterHash}:route:{topicKey}
|
|
101
|
-
cross-tab-worker-databus:{clusterHash}:subscriber:{topicKey}:{
|
|
101
|
+
cross-tab-worker-databus:{clusterHash}:subscriber:{topicKey}:{workerId}
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
与旧的单 JSON 路由表不同,subscriber
|
|
104
|
+
与旧的单 JSON 路由表不同,subscriber 使用**每个 Runtime** 一条独立 key——是 `workerId` 而不是 `tabId`,因为一个 document 可以运行多个共享同一 Tab 的 Runtime。当 Tab A 和 Tab B 并发订阅/退订时,它们不会对同一个 `subscribers[]` 做读-改-写,从结构上降低丢失更新的概率;同一 Tab 内两个 Runtime 之一退订时,删除的也只是它自己的记录,兄弟 Runtime 的 route 与 transport 订阅继续有效。
|
|
105
105
|
|
|
106
106
|
### Worker 记录
|
|
107
107
|
|
|
@@ -182,7 +182,7 @@ topic
|
|
|
182
182
|
└─ createOpaqueKey(topic) → topicKey
|
|
183
183
|
├─ route:{topicKey}
|
|
184
184
|
│ └─ workerId / tabId / generation / confirmedAt
|
|
185
|
-
└─ subscriber:{topicKey}:{
|
|
185
|
+
└─ subscriber:{topicKey}:{workerId}
|
|
186
186
|
|
|
187
187
|
BroadcastChannel CONTROL
|
|
188
188
|
└─ topic + topicKey + sourceWorkerId + targetWorkerId + action
|
|
@@ -252,7 +252,7 @@ sequenceDiagram
|
|
|
252
252
|
|
|
253
253
|
App->>RuntimeA: subscribe(topic, handler)
|
|
254
254
|
RuntimeA->>RuntimeA: 计算 topicKey
|
|
255
|
-
RuntimeA->>Storage: 写 subscriber:{topicKey}:{
|
|
255
|
+
RuntimeA->>Storage: 写 subscriber:{topicKey}:{workerId}
|
|
256
256
|
RuntimeA->>Storage: 读取或创建 route:{topicKey}
|
|
257
257
|
RuntimeA->>Channel: CONTROL/SUBSCRIBE(topic, topicKey, targetWorkerId)
|
|
258
258
|
Channel->>RuntimeB: 投递控制消息
|
|
@@ -266,7 +266,7 @@ sequenceDiagram
|
|
|
266
266
|
RuntimeA->>App: 调用 handler(payload)
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
第二个 Tab 订阅同一 Topic 时,只新增自己的 `subscriber:{topicKey}:{
|
|
269
|
+
第二个 Tab 订阅同一 Topic 时,只新增自己的 `subscriber:{topicKey}:{workerId}`;只要现有 route 的 owner 仍存活,就不会再次建立一条 transport 订阅。退订时删除当前 Runtime 的 subscriber 记录;若它已是最后一条,同一个 Runtime 顺带删除 route,并向 route 记录的 worker 发出 `CONTROL/UNSUBSCRIBE`——收到的一方就此放弃 ownership 并释放 transport 订阅。
|
|
270
270
|
|
|
271
271
|
### 控制台排查
|
|
272
272
|
|
|
@@ -313,7 +313,7 @@ console.table(__bus.getClusterSnapshot().routes)
|
|
|
313
313
|
| `knownTopics` | `WorkerClusterRuntime` | `topicKey` | 明文 `topic` | FIFO 扫描上限 500,会跳过持有的 key 与本次正在记忆的 key,因此所有条目都被持有时上限会失守 | 反查缓存;也是无 storage 模式下明文的唯一来源 |
|
|
314
314
|
| 存储 `worker:` | 持久化 | `clusterHash:…:worker:{workerId}` | JSON `WorkerRecord` | 心跳刷新;超过 `workerTtlMs` 被清理 | 跨 Tab 存活发现 |
|
|
315
315
|
| 存储 `route:` | 持久化 | `clusterHash:…:route:{topicKey}` | JSON `WorkerRoute` | 由订阅方创建/盖章;无订阅者且 TTL 过期时清理 | 跨 Tab owner 映射 |
|
|
316
|
-
| 存储 `subscriber:` | 持久化 | `clusterHash:…:subscriber:{topicKey}:{
|
|
316
|
+
| 存储 `subscriber:` | 持久化 | `clusterHash:…:subscriber:{topicKey}:{workerId}` | JSON `TopicSubscriberRecord` | 每次 Runtime 订阅写入;该 Runtime 死亡时清理(旧版按 Tab 落键的记录随 Tab 清理) | 跨 Tab 订阅意图 |
|
|
317
317
|
|
|
318
318
|
**三种内存 Topic 形态的关系**(`knownTopics` ↔ `assignedTopics` ↔ 四个明文集合):
|
|
319
319
|
|
|
@@ -388,7 +388,7 @@ sequenceDiagram
|
|
|
388
388
|
|
|
389
389
|
App->>Bus: subscribe(topic, handler)
|
|
390
390
|
Bus->>Bus: 当前 Tab 第一个 handler?
|
|
391
|
-
Bus->>Route: 写 subscriber:{topicKey}:{
|
|
391
|
+
Bus->>Route: 写 subscriber:{topicKey}:{workerId}
|
|
392
392
|
Route-->>Bus: 当前 owner
|
|
393
393
|
alt owner 不存在或无效
|
|
394
394
|
Bus->>Route: 写最低负载 owner
|
|
@@ -416,7 +416,7 @@ sequenceDiagram
|
|
|
416
416
|
应用层: subscribe(topic, handler)
|
|
417
417
|
→ topicHandlers 0→1
|
|
418
418
|
→ cluster.subscribe(topic) → subscribedTopics.add(topic)
|
|
419
|
-
→ 写 subscriber:{topicKey}:{
|
|
419
|
+
→ 写 subscriber:{topicKey}:{workerId}
|
|
420
420
|
→ readRoute(topicKey)
|
|
421
421
|
→ 无 route: 选择最低负载 Worker,写 route,sendControl(SUBSCRIBE)
|
|
422
422
|
→ owner 收到 CONTROL/SUBSCRIBE
|
|
@@ -452,7 +452,7 @@ sequenceDiagram
|
|
|
452
452
|
2. owner 执行 `transport.publish(topic, data)`。由于只有 owner 持有该 Topic 的真实 transport 订阅,服务器只会把这条 publication 回推给唯一一个 Worker。
|
|
453
453
|
3. owner 仅当 `isAssigned(topic)` 仍成立时才接受该 publication;过期 owner 的陈旧消息被丢弃——保证扇出路径只有单一消息源。
|
|
454
454
|
4. owner 通过 BroadcastChannel 广播 `EVENT/DATABUS_PUBLICATION`;自身 Tab 也有本地订阅时直接分发一次。BroadcastChannel 从不把消息回传给发送者,因此不会重复分发。
|
|
455
|
-
5. 其余每个 Tab 收到 `EVENT`
|
|
455
|
+
5. 其余每个 Tab 收到 `EVENT` 后,仅当自己的订阅意图覆盖该 Topic 时才调用本地 handler——这道门读的是内存中的订阅集合,而 `subscriber:{topicKey}:{workerId}` 记录只是告诉其他 peer 这份意图存在;没有本地订阅的 Tab 直接丢弃。
|
|
456
456
|
|
|
457
457
|
可选的 publication 元数据(`messageId` 与 `timestamp`)与 payload 走同一条路径:`CONTROL/PUBLISH` → transport/服务器 → `DataBusMessage` → `EVENT` 扇出。它不会写入协调存储。各 transport 会在三处分发门之前,把旧 payload 格式与标准 `DataBusPublicationEnvelope` 统一规范化。
|
|
458
458
|
|
|
@@ -493,7 +493,7 @@ SDK 当前刻意不在 Service Worker 中承载实时 transport。Service Worker
|
|
|
493
493
|
|
|
494
494
|
1. **`isAssigned(topic)`** — 在 owner Worker 上检查(`handleTransportMessage`)。如果该 topic 已不再分配给此 worker(比如前一个 ownership 窗口的过期消息),立即丢弃。这是外层关卡:防止非 owner 广播。
|
|
495
495
|
2. **`broadcastEvent('DATABUS_PUBLICATION', message)`** — 仅当 `isAssigned` 通过后调用。owner Worker 通过 BroadcastChannel `EVENT` 将消息扇出到所有 Tab。每个 Tab 收到事件但暂不分发——必须通过内层关卡。
|
|
496
|
-
3. **`hasLocalSubscriber(topic)`** — 在收到 `EVENT` 的每个 Tab
|
|
496
|
+
3. **`hasLocalSubscriber(topic)`** — 在收到 `EVENT` 的每个 Tab 上检查。它读的是内存中的订阅集合(含通配 pattern),不是持久化的 subscriber 记录;仅当自己的订阅覆盖该 topic 时才调用已注册的 handler。无本地订阅的 Tab 静默丢弃。
|
|
497
497
|
|
|
498
498
|
这三道关卡提供的是**每次已接受的 transport publication 至多扇出一次**:
|
|
499
499
|
- 外层关卡(`isAssigned`)防止过期 owner 重复广播。
|
|
@@ -523,11 +523,13 @@ Transport 消息 → isAssigned(topic)? → 是 → broadcastEvent(EVENT)
|
|
|
523
523
|
|
|
524
524
|
正常关闭或进入 BFCache 时,`pagehide` 暂停 Runtime:删除 Worker 和 subscriber 记录、让出实际 owner、关闭底层 transport,但在内存中保留业务订阅意图。`pageshow` 恢复页面后,DataBus 重建 Worker/连接,Runtime 自动重新注册、恢复 subscriber 记录并协调 Topic,业务无需重新调用 `subscribe`。
|
|
525
525
|
|
|
526
|
-
#### Tab
|
|
526
|
+
#### Tab 身份:刷新、`window.open` 与复制标签页
|
|
527
527
|
|
|
528
|
-
每个 Runtime 使用 `sessionStorage` 保存 `tabId`,刷新页面时保持稳定;`workerId` 则在每次 Runtime
|
|
528
|
+
每个 Runtime 使用 `sessionStorage` 保存 `tabId`,刷新页面时保持稳定;`workerId` 则在每次 Runtime 创建时使用随机后缀生成。继承这份存储值的新 document 有两种,但只有一种应当保留它。刷新是**同一个** Tab 重新进入页面,值无人占用,因此复用。浏览器复制出的标签页(`window.open()` 或浏览器自带的 Duplicate tab)则是**第二个**存活 document 持有一份副本,两者不能呈现同一个身份:subscriber 记录以 `tabId` 为键,副本会在每次写入时覆盖原标签页的记录、并在退订时把它们删掉。
|
|
529
529
|
|
|
530
|
-
|
|
530
|
+
两种线索性质不同。`window.open()` 会留下 `window.opener`,SDK 因此在检测到 opener 时丢弃被复制的 `sessionStorage` id 并重新生成;应用侧仍建议使用 `noopener`。浏览器自带的 Duplicate tab 完全没有 opener,SDK 改为探测本集群的 Worker 记录——它们以随机的 `workerId` 存在 `localStorage` 中,不会随 session 一起被复制。若存在一条心跳仍新鲜、且带着被继承 id 的记录,说明另一个存活 document 正在使用它,复制出的标签页就改领一个新 id,并写回以供水同 document 内后续 Runtime 共用。
|
|
531
|
+
|
|
532
|
+
该探测每个 document 只执行一次,位置在构造函数中。刷新之所以能被识别,是因为 `pause()` 会删除离开的 document 的 Worker 记录并在页面消失前 flush 这次删除;异常退出留下的记录会存活至多一个 `workerTtlMs`,在这个窗口内刷新会领到新 id(随后由正常的 TTL 路径清理该陈旧记录)。诊断记录按 `tabId + workerId` 保存,避免 Worker 重启或 handoff 窗口内的新旧快照互相覆盖。
|
|
531
533
|
|
|
532
534
|
`visibilitychange` 不删除业务订阅,也不迁移已经建立的 route。隐藏 Tab 继续持有自己已有的 Topic,也仍能收到其他 owner 广播的数据。可见性只影响全新 Topic 首次选择 owner 时的候选集合。
|
|
533
535
|
|
package/docs/zh/benchmarks.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
# 浏览器基准趋势
|
|
4
4
|
|
|
5
|
-
> 数据截至 2026-10-
|
|
5
|
+
> 数据截至 2026-10-30,基于 97 份归档的 `bench-results/browser-*.json` 报告(运行 `pnpm bench:browser` 追加一份;用 `node scripts/bench-trend.mjs` 重新生成本文档)。
|
|
6
6
|
|
|
7
7
|
发布门禁的对比基线是 `pnpm bench:compare --fail-above-pct 50`:将最新报告与其之前若干报告中同一指标的中位数比较,*并且*要求新值超过这些样本中的最大值(50% 上限用于吸收共享 runner 的噪声;此前只看"上一份报告"并不稳定,因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳;而在两档交替的样本上,中位数只有在这两档混合分布时才稳定,因此单看百分比仍可能纯粹因为档位切换而失败)。被第二个条件放过的指标会显式列在 “within-baseline, not gated” 里,而不是悄悄算作通过。本文记录长期趋势:数值为逐指标延迟,越低越好;最后一列是最近 5 份报告内的最优值,而不是历史纪录——页内基准矩阵在 2026 年 9 月初变更过测量语义,更早的报告不可比。
|
|
8
8
|
|
|
9
9
|
<!-- BENCH-TREND:BEGIN (machine-generated table) -->
|
|
10
10
|
| 指标 | 上次 (ms) | 本次 (ms) | Δ | 近 5 次最优 (ms) |
|
|
11
11
|
|---|---|---|---|---|
|
|
12
|
-
| publish per-message (ms, lower is better) — dedicated |
|
|
13
|
-
| publish per-message (ms, lower is better) — shared |
|
|
14
|
-
| wildcard dispatch ×1000 (ms, lower is better) |
|
|
15
|
-
| publishBatch ×1000 (ms, lower is better) |
|
|
16
|
-
| dedup ×1000 (ms, lower is better) |
|
|
17
|
-
| trace + publish ×1000 (ms, lower is better) | 5.
|
|
18
|
-
| first-packet cold dispatch (ms, lower is better) | 0 | 0 | +0.
|
|
12
|
+
| publish per-message (ms, lower is better) — dedicated | 39.1206 | 37.9266 | -1.19 | 37.9266 |
|
|
13
|
+
| publish per-message (ms, lower is better) — shared | 34.1177 | 34.5476 | +0.43 | 33.8229 |
|
|
14
|
+
| wildcard dispatch ×1000 (ms, lower is better) | 6.7 | 6.9 | +0.20 | 6 |
|
|
15
|
+
| publishBatch ×1000 (ms, lower is better) | 4.3 | 4.1 | -0.20 | 3.9 |
|
|
16
|
+
| dedup ×1000 (ms, lower is better) | 16.1 | 16.7 | +0.60 | 13.2 |
|
|
17
|
+
| trace + publish ×1000 (ms, lower is better) | 5.4 | 5.1 | -0.30 | 5.1 |
|
|
18
|
+
| first-packet cold dispatch (ms, lower is better) | 0 | 0.1 | +0.10 | 0 |
|
|
19
19
|
<!-- BENCH-TREND:END -->
|
|
20
20
|
|
|
21
21
|
说明:
|