cross-tab-worker-databus 0.20.87 → 0.20.89
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-session.d.ts +1 -0
- package/dist/centrifuge-session.d.ts.map +1 -1
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +55 -8
- package/dist/centrifuge.js.map +2 -2
- package/dist/centrifuge.shared.worker.js +38 -6
- package/dist/centrifuge.shared.worker.js.map +2 -2
- package/dist/centrifuge.worker.js +38 -6
- package/dist/centrifuge.worker.js.map +2 -2
- package/dist/{chunk-ZNHJ5OMY.js → chunk-77BQELW4.js} +69 -29
- package/dist/{chunk-ZNHJ5OMY.js.map → chunk-77BQELW4.js.map} +3 -3
- package/dist/cjs/centrifuge.cjs +122 -35
- package/dist/cjs/centrifuge.cjs.map +3 -3
- package/dist/cjs/index.cjs +76 -30
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/core/data-bus.d.ts +6 -0
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/core/replay-manager.d.ts.map +1 -1
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +2 -2
- package/dist/websocket.d.ts.map +1 -1
- package/docs/api.md +4 -4
- package/docs/architecture.md +8 -6
- package/docs/capabilities.md +1 -1
- package/docs/configuration.md +1 -1
- package/docs/roadmap.md +18 -1
- package/docs/zh/api.md +4 -4
- package/docs/zh/architecture.md +8 -6
- package/docs/zh/capabilities.md +1 -1
- package/docs/zh/configuration.md +1 -1
- package/docs/zh/roadmap.md +18 -1
- package/package.json +1 -1
|
@@ -1533,8 +1533,9 @@ var DataBusTraceReporter = class {
|
|
|
1533
1533
|
/** Start the periodic metrics flush interval. No-op when mode is 'events'
|
|
1534
1534
|
* (no metrics to emit), when disabled, or when already running. */
|
|
1535
1535
|
start() {
|
|
1536
|
-
if (!this.enabled
|
|
1536
|
+
if (!this.enabled) return;
|
|
1537
1537
|
this.stopped = false;
|
|
1538
|
+
if (this.intervalHandle || this.mode === TRACE_MODE.EVENTS) return;
|
|
1538
1539
|
this.intervalStartedAt = this.now();
|
|
1539
1540
|
this.intervalHandle = setInterval(() => this.flush(), this.metricsIntervalMs);
|
|
1540
1541
|
}
|
|
@@ -1547,6 +1548,7 @@ var DataBusTraceReporter = class {
|
|
|
1547
1548
|
}
|
|
1548
1549
|
stop() {
|
|
1549
1550
|
this.stopped = true;
|
|
1551
|
+
this.pendingEvents = [];
|
|
1550
1552
|
this.pause();
|
|
1551
1553
|
}
|
|
1552
1554
|
/** Synchronous sink state for diagnostics: whether delivery is async and how
|
|
@@ -1557,7 +1559,7 @@ var DataBusTraceReporter = class {
|
|
|
1557
1559
|
}
|
|
1558
1560
|
/** Record an instantaneous trace event (lifecycle, status, error, etc.). */
|
|
1559
1561
|
event(event) {
|
|
1560
|
-
if (!this.enabled || this.mode === TRACE_MODE.METRICS) return;
|
|
1562
|
+
if (!this.enabled || this.stopped || this.mode === TRACE_MODE.METRICS) return;
|
|
1561
1563
|
this.emit({ ...event, timestamp: this.now() });
|
|
1562
1564
|
}
|
|
1563
1565
|
/** Synchronous snapshot of the current metrics window without resetting it.
|
|
@@ -1640,7 +1642,7 @@ var DataBusTraceReporter = class {
|
|
|
1640
1642
|
* Extracted so the four record / flush methods share one guard expression
|
|
1641
1643
|
* instead of repeating `!this.enabled || this.mode === 'events'` at each. */
|
|
1642
1644
|
get metricsActive() {
|
|
1643
|
-
return this.enabled && this.mode !== TRACE_MODE.EVENTS;
|
|
1645
|
+
return this.enabled && !this.stopped && this.mode !== TRACE_MODE.EVENTS;
|
|
1644
1646
|
}
|
|
1645
1647
|
/** Emit the accumulated metrics snapshot if the interval is active. */
|
|
1646
1648
|
flush() {
|
|
@@ -1942,6 +1944,8 @@ var ReplayManager = class {
|
|
|
1942
1944
|
* or stopped bus does not keep hammering the store) and stop the sweep. */
|
|
1943
1945
|
suspend() {
|
|
1944
1946
|
this.retryGeneration += 1;
|
|
1947
|
+
this.pendingReplayPersistence = [];
|
|
1948
|
+
this.retentionCutoff = null;
|
|
1945
1949
|
this.stop();
|
|
1946
1950
|
}
|
|
1947
1951
|
/** Drop all in-memory buffers (used on full teardown). */
|
|
@@ -2040,19 +2044,20 @@ var ReplayManager = class {
|
|
|
2040
2044
|
this.retentionCutoff = cutoff;
|
|
2041
2045
|
}
|
|
2042
2046
|
if (this.retentionCleanup) return;
|
|
2047
|
+
const generation = this.retryGeneration;
|
|
2043
2048
|
this.retentionCleanup = (async () => {
|
|
2044
|
-
while (this.retentionCutoff !== null) {
|
|
2049
|
+
while (this.retentionCutoff !== null && generation === this.retryGeneration) {
|
|
2045
2050
|
const nextCutoff = this.retentionCutoff;
|
|
2046
2051
|
this.retentionCutoff = null;
|
|
2047
2052
|
try {
|
|
2048
2053
|
await this.persistence.clearBefore(nextCutoff);
|
|
2049
2054
|
} catch (error) {
|
|
2050
|
-
this.onPersistenceError(error);
|
|
2055
|
+
if (generation === this.retryGeneration) this.onPersistenceError(error);
|
|
2051
2056
|
}
|
|
2052
2057
|
}
|
|
2053
2058
|
})().finally(() => {
|
|
2054
2059
|
this.retentionCleanup = null;
|
|
2055
|
-
if (this.retentionCutoff !== null) {
|
|
2060
|
+
if (this.retentionCutoff !== null && generation === this.retryGeneration) {
|
|
2056
2061
|
this.scheduleRetentionCleanup(this.retentionCutoff);
|
|
2057
2062
|
}
|
|
2058
2063
|
});
|
|
@@ -2069,7 +2074,9 @@ var ReplayManager = class {
|
|
|
2069
2074
|
attempt += 1;
|
|
2070
2075
|
try {
|
|
2071
2076
|
if (generation !== this.retryGeneration) throw new PersistenceRetryCancelledError();
|
|
2072
|
-
|
|
2077
|
+
const result = await operation();
|
|
2078
|
+
if (generation !== this.retryGeneration) throw new PersistenceRetryCancelledError();
|
|
2079
|
+
return result;
|
|
2073
2080
|
} catch (error) {
|
|
2074
2081
|
if (error instanceof PersistenceRetryCancelledError || generation !== this.retryGeneration) {
|
|
2075
2082
|
throw new PersistenceRetryCancelledError();
|
|
@@ -2203,7 +2210,7 @@ var DedupManager = class {
|
|
|
2203
2210
|
};
|
|
2204
2211
|
|
|
2205
2212
|
// src/core/version.ts
|
|
2206
|
-
var SDK_VERSION = true ? "0.20.
|
|
2213
|
+
var SDK_VERSION = true ? "0.20.89" : "";
|
|
2207
2214
|
|
|
2208
2215
|
// src/core/data-bus.ts
|
|
2209
2216
|
var DEFAULT_REPLAY_MAX_PER_TOPIC = 100;
|
|
@@ -2397,10 +2404,7 @@ var CrossTabDataBus = class {
|
|
|
2397
2404
|
this.suspendTransport();
|
|
2398
2405
|
},
|
|
2399
2406
|
onResume: () => {
|
|
2400
|
-
this.
|
|
2401
|
-
this.trace.start();
|
|
2402
|
-
this.startDedupSweep();
|
|
2403
|
-
this.replayManager.start();
|
|
2407
|
+
this.resumeSuspendedResources();
|
|
2404
2408
|
this.resumeTransport();
|
|
2405
2409
|
},
|
|
2406
2410
|
onDiagnostic: (event) => {
|
|
@@ -2430,15 +2434,19 @@ var CrossTabDataBus = class {
|
|
|
2430
2434
|
if (!transportDown) return Promise.resolve();
|
|
2431
2435
|
this.activeConfig = config;
|
|
2432
2436
|
this.resetFailureState();
|
|
2433
|
-
|
|
2437
|
+
const resumingFromSuspend = this.suspended;
|
|
2438
|
+
if (resumingFromSuspend) this.resumeSuspendedResources();
|
|
2439
|
+
const opening2 = this.reopenTransport();
|
|
2440
|
+
if (resumingFromSuspend) this.cluster.start();
|
|
2441
|
+
return opening2;
|
|
2434
2442
|
}
|
|
2435
2443
|
this.started = true;
|
|
2436
2444
|
this.stopping = false;
|
|
2437
2445
|
this.suspended = false;
|
|
2438
2446
|
this.activeConfig = config;
|
|
2439
2447
|
this.resetFailureState();
|
|
2440
|
-
this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.START });
|
|
2441
2448
|
this.trace.start();
|
|
2449
|
+
this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.START });
|
|
2442
2450
|
this.startDedupSweep();
|
|
2443
2451
|
this.replayManager.start();
|
|
2444
2452
|
this.updateStatus(WORKER_STATUS.CONNECTING);
|
|
@@ -2553,6 +2561,7 @@ var CrossTabDataBus = class {
|
|
|
2553
2561
|
this.transportReady = false;
|
|
2554
2562
|
const chainedPendingStop = this.pendingStop;
|
|
2555
2563
|
const isCurrentLifecycle = () => lifecycleEpoch === this.lifecycleEpoch;
|
|
2564
|
+
let startupInProgress = true;
|
|
2556
2565
|
return before.catch(() => void 0).then(() => {
|
|
2557
2566
|
if (!isCurrentLifecycle() || this.stopping || this.suspended) return;
|
|
2558
2567
|
if (this.pendingStop === chainedPendingStop) this.pendingStop = null;
|
|
@@ -2563,13 +2572,16 @@ var CrossTabDataBus = class {
|
|
|
2563
2572
|
if (isCurrentLifecycle()) this.handleTransportMessage(message);
|
|
2564
2573
|
},
|
|
2565
2574
|
onStatus: (status) => {
|
|
2566
|
-
if (isCurrentLifecycle())
|
|
2575
|
+
if (isCurrentLifecycle()) {
|
|
2576
|
+
this.updateStatus(status, status !== WORKER_STATUS.ERROR || !startupInProgress);
|
|
2577
|
+
}
|
|
2567
2578
|
},
|
|
2568
2579
|
onError: (error) => {
|
|
2569
2580
|
if (isCurrentLifecycle()) this.reportError(error);
|
|
2570
2581
|
}
|
|
2571
2582
|
})
|
|
2572
2583
|
).then(() => {
|
|
2584
|
+
startupInProgress = false;
|
|
2573
2585
|
if (!isCurrentLifecycle()) return;
|
|
2574
2586
|
if (this.status === WORKER_STATUS.ERROR) {
|
|
2575
2587
|
throw new Error("Transport failed during startup.");
|
|
@@ -2583,18 +2595,21 @@ var CrossTabDataBus = class {
|
|
|
2583
2595
|
});
|
|
2584
2596
|
}).catch((error) => {
|
|
2585
2597
|
if (!isCurrentLifecycle()) throw error;
|
|
2598
|
+
startupInProgress = false;
|
|
2586
2599
|
if (stopClusterOnFailure) this.started = false;
|
|
2587
2600
|
if (!this.pendingStop) {
|
|
2588
2601
|
this.pendingStop = this.createStopPromise();
|
|
2589
2602
|
}
|
|
2590
2603
|
this.transportReady = false;
|
|
2591
|
-
this.updateStatus(WORKER_STATUS.ERROR);
|
|
2592
|
-
this.reportError(error);
|
|
2593
2604
|
if (stopClusterOnFailure) {
|
|
2594
2605
|
this.stopping = true;
|
|
2595
2606
|
this.cluster.stop();
|
|
2596
2607
|
this.stopping = false;
|
|
2597
2608
|
}
|
|
2609
|
+
this.recordError(error);
|
|
2610
|
+
this.startPromise = null;
|
|
2611
|
+
this.updateStatus(WORKER_STATUS.ERROR);
|
|
2612
|
+
this.notifyError(error);
|
|
2598
2613
|
throw error;
|
|
2599
2614
|
});
|
|
2600
2615
|
}
|
|
@@ -2791,7 +2806,7 @@ var CrossTabDataBus = class {
|
|
|
2791
2806
|
getHealthSummary() {
|
|
2792
2807
|
const transport = this.transport;
|
|
2793
2808
|
const transportDown = this.status !== WORKER_STATUS.CONNECTED;
|
|
2794
|
-
const state = !this.started ? HEALTH_STATE.STOPPED : this.suspended ? HEALTH_STATE.SUSPENDED : transportDown ? this.recoveryExhausted ? HEALTH_STATE.DEGRADED : this.status === WORKER_STATUS.CONNECTING && this.recoveryAttempt === 0 ? HEALTH_STATE.STARTING : HEALTH_STATE.RECOVERING : HEALTH_STATE.HEALTHY;
|
|
2809
|
+
const state = !this.started || this.stopping ? HEALTH_STATE.STOPPED : this.suspended ? HEALTH_STATE.SUSPENDED : transportDown ? this.recoveryExhausted ? HEALTH_STATE.DEGRADED : this.status === WORKER_STATUS.CONNECTING && this.recoveryAttempt === 0 ? HEALTH_STATE.STARTING : HEALTH_STATE.RECOVERING : HEALTH_STATE.HEALTHY;
|
|
2795
2810
|
return {
|
|
2796
2811
|
healthy: state === HEALTH_STATE.HEALTHY,
|
|
2797
2812
|
state,
|
|
@@ -2862,7 +2877,7 @@ var CrossTabDataBus = class {
|
|
|
2862
2877
|
this.canceledQueuedStartToken = this.queuedStartToken;
|
|
2863
2878
|
this.queuedStart = null;
|
|
2864
2879
|
}
|
|
2865
|
-
if (this.stopPromise) return this.stopPromise;
|
|
2880
|
+
if (this.stopPromise && this.stopping) return this.stopPromise;
|
|
2866
2881
|
if (!this.started && !this.startPromise && !this.pendingStop && !this.transportReady) {
|
|
2867
2882
|
return Promise.resolve();
|
|
2868
2883
|
}
|
|
@@ -2958,7 +2973,7 @@ var CrossTabDataBus = class {
|
|
|
2958
2973
|
* Propagate a status change to the cluster, trace, and all registered
|
|
2959
2974
|
* status handlers. On reconnect, re-subscribe any topics assigned to us.
|
|
2960
2975
|
*/
|
|
2961
|
-
updateStatus(status) {
|
|
2976
|
+
updateStatus(status, notifyHandlers = true) {
|
|
2962
2977
|
const previousStatus = this.status;
|
|
2963
2978
|
this.status = status;
|
|
2964
2979
|
if (status === WORKER_STATUS.CONNECTED) this.transportHasConnected = true;
|
|
@@ -3010,9 +3025,9 @@ var CrossTabDataBus = class {
|
|
|
3010
3025
|
} else if (status === WORKER_STATUS.ERROR) {
|
|
3011
3026
|
this.releaseRecoveryGate();
|
|
3012
3027
|
}
|
|
3013
|
-
this.invokeHandlers(this.statusHandlers, (handler) => handler(status));
|
|
3028
|
+
if (notifyHandlers) this.invokeHandlers(this.statusHandlers, (handler) => handler(status));
|
|
3014
3029
|
}
|
|
3015
|
-
|
|
3030
|
+
recordError(error, source = FAILURE_SOURCE.TRANSPORT) {
|
|
3016
3031
|
const at = this.now();
|
|
3017
3032
|
if (source === FAILURE_SOURCE.TRANSPORT) {
|
|
3018
3033
|
this.lastError = error;
|
|
@@ -3032,8 +3047,14 @@ var CrossTabDataBus = class {
|
|
|
3032
3047
|
type: TRACE_EVENT_TYPE.ERROR,
|
|
3033
3048
|
source: source === FAILURE_SOURCE.TRANSPORT ? TRACE_ERROR_SOURCE.TRANSPORT : TRACE_ERROR_SOURCE.OPERATION
|
|
3034
3049
|
});
|
|
3050
|
+
}
|
|
3051
|
+
notifyError(error) {
|
|
3035
3052
|
this.invokeHandlers(this.errorHandlers, (handler) => handler(error), INVOKE_LABEL.ERROR_HANDLER);
|
|
3036
3053
|
}
|
|
3054
|
+
reportError(error, source = FAILURE_SOURCE.TRANSPORT) {
|
|
3055
|
+
this.recordError(error, source);
|
|
3056
|
+
this.notifyError(error);
|
|
3057
|
+
}
|
|
3037
3058
|
/** Report a persistence failure to the trace and the unified failure ledger,
|
|
3038
3059
|
* unless it is a {@link PersistenceRetryCancelledError} cancellation from a
|
|
3039
3060
|
* lifecycle transition (teardown should stay quiet). */
|
|
@@ -3096,6 +3117,15 @@ var CrossTabDataBus = class {
|
|
|
3096
3117
|
}
|
|
3097
3118
|
}
|
|
3098
3119
|
}
|
|
3120
|
+
/** Resume the resources paused by a pagehide suspension. Both the native
|
|
3121
|
+
* pageshow path and explicit start() must run this so an explicit resume
|
|
3122
|
+
* cannot leave trace metrics and periodic cleanup timers permanently off. */
|
|
3123
|
+
resumeSuspendedResources() {
|
|
3124
|
+
this.trace.start();
|
|
3125
|
+
this.trace.event({ type: TRACE_EVENT_TYPE.LIFECYCLE, action: TRACE_LIFECYCLE_ACTION.RESUME });
|
|
3126
|
+
this.startDedupSweep();
|
|
3127
|
+
this.replayManager.start();
|
|
3128
|
+
}
|
|
3099
3129
|
/**
|
|
3100
3130
|
* Suspend the transport when the tab goes hidden. Stops the transport and
|
|
3101
3131
|
* clears subscription state so it will be re-established on resume.
|
|
@@ -3108,8 +3138,11 @@ var CrossTabDataBus = class {
|
|
|
3108
3138
|
this.transportReady = false;
|
|
3109
3139
|
this.transportSubscribedTopics.clear();
|
|
3110
3140
|
this.updateStatus(WORKER_STATUS.DISCONNECTED);
|
|
3111
|
-
if (this.pendingStop)
|
|
3112
|
-
|
|
3141
|
+
if (this.pendingStop && (this.startPromise === null || this.startPromise === this.pendingStop)) {
|
|
3142
|
+
this.startPromise = this.pendingStop;
|
|
3143
|
+
return;
|
|
3144
|
+
}
|
|
3145
|
+
const pending = this.startPromise ?? this.pendingStop ?? Promise.resolve();
|
|
3113
3146
|
const stopping = pending.catch(() => void 0).then(() => this.transport.stop()).catch((error) => this.reportError(error));
|
|
3114
3147
|
this.startPromise = stopping;
|
|
3115
3148
|
this.pendingStop = stopping;
|
|
@@ -3204,10 +3237,17 @@ var CrossTabDataBus = class {
|
|
|
3204
3237
|
ready = this.reopenTransport();
|
|
3205
3238
|
}
|
|
3206
3239
|
if (!ready || this.stopping) return;
|
|
3207
|
-
void ready.then(
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3240
|
+
void ready.then(
|
|
3241
|
+
() => {
|
|
3242
|
+
if (!this.started || this.stopping || this.suspended) return;
|
|
3243
|
+
return operation();
|
|
3244
|
+
},
|
|
3245
|
+
// The opening promise reports its own lifecycle failure through
|
|
3246
|
+
// openTransport(). Swallowing it here prevents a stale startup
|
|
3247
|
+
// rejection from being recorded again after an onStatus/onError
|
|
3248
|
+
// callback has already started and reset the ledger for a retry.
|
|
3249
|
+
() => void 0
|
|
3250
|
+
).catch((error) => this.reportError(error));
|
|
3211
3251
|
}
|
|
3212
3252
|
/**
|
|
3213
3253
|
* Publications started after teardown begins cannot reach any transport.
|
|
@@ -3302,4 +3342,4 @@ export {
|
|
|
3302
3342
|
parseDataBusPublication,
|
|
3303
3343
|
selectWorkerBackend
|
|
3304
3344
|
};
|
|
3305
|
-
//# sourceMappingURL=chunk-
|
|
3345
|
+
//# sourceMappingURL=chunk-77BQELW4.js.map
|