cross-tab-worker-databus 0.20.70 → 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 +209 -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-IKBJIREH.js → chunk-PW63EWIK.js} +1090 -476
- 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 +1405 -621
- 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 +1469 -688
- 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 -66
- 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 +4 -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 +231 -125
- 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 +78 -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 +90 -5
- package/package.json +39 -16
- package/dist/chunk-IKBJIREH.js.map +0 -7
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DedupManager — bounded duplicate suppression for publications carrying
|
|
3
|
+
* `messageId`.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from CrossTabDataBus so the seen-ID map, adaptive TTL, and sweep
|
|
6
|
+
* timer live in one self-contained unit with their own lifecycle. The DataBus
|
|
7
|
+
* keeps a thin delegation: `isDuplicate()` on the inbound path, `start`/`stop`
|
|
8
|
+
* on the lifecycle transitions, and `getStats()`/`reset()` on the diagnostics
|
|
9
|
+
* surface.
|
|
10
|
+
*
|
|
11
|
+
* Deduplication is opt-in: an instance is only created when the DataBus was
|
|
12
|
+
* configured with `dedup` options, so the zero-overhead default (no map, no
|
|
13
|
+
* timer) is preserved.
|
|
14
|
+
*/
|
|
15
|
+
import type { DataBusTraceReporter } from './trace';
|
|
16
|
+
/** Opt-in bounded duplicate suppression for publications carrying `messageId`. */
|
|
17
|
+
export interface DataBusDedupOptions {
|
|
18
|
+
/** Max remembered message IDs before the oldest (FIFO) entry is evicted.
|
|
19
|
+
* Default 1_000. */
|
|
20
|
+
maxEntries?: number;
|
|
21
|
+
/** Time-to-live for a remembered ID. Default 60_000 ms. */
|
|
22
|
+
ttlMs?: number;
|
|
23
|
+
/** Optional periodic sweep interval for quiet-topic expiry. */
|
|
24
|
+
sweepMs?: number;
|
|
25
|
+
/** Injectable epoch clock for deterministic tests and non-wall-clock hosts. */
|
|
26
|
+
now?: () => number;
|
|
27
|
+
/** Optional adaptive TTL bounds; enabled only when both are provided. */
|
|
28
|
+
adaptiveTtl?: {
|
|
29
|
+
minMs: number;
|
|
30
|
+
maxMs: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Bounded deduplication counters for diagnostics and health checks. */
|
|
34
|
+
export interface DataBusDedupStats {
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
/** Currently remembered message IDs. */
|
|
37
|
+
tracked: number;
|
|
38
|
+
/** Publications suppressed as duplicates since the last reset. */
|
|
39
|
+
suppressed: number;
|
|
40
|
+
/** Publications accepted (tracked) since the last reset. */
|
|
41
|
+
accepted: number;
|
|
42
|
+
/** Effective TTL when adaptive bounds are configured. */
|
|
43
|
+
ttlMs?: number;
|
|
44
|
+
}
|
|
45
|
+
/** Resolved constructor options after defaults are applied. */
|
|
46
|
+
export interface DedupManagerOptions {
|
|
47
|
+
/** Whether deduplication is enabled at all (false → no-op instance). */
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
maxEntries: number;
|
|
50
|
+
ttlMs: number;
|
|
51
|
+
adaptiveBounds?: {
|
|
52
|
+
minMs: number;
|
|
53
|
+
maxMs: number;
|
|
54
|
+
} | undefined;
|
|
55
|
+
/** Optional periodic sweep interval for quiet-topic expiry. */
|
|
56
|
+
sweepMs?: number | undefined;
|
|
57
|
+
/** Injectable epoch clock; also used as the message-arrival clock. */
|
|
58
|
+
now: () => number;
|
|
59
|
+
/** Trace sink for suppression events and metrics counters. */
|
|
60
|
+
trace: DataBusTraceReporter;
|
|
61
|
+
}
|
|
62
|
+
export declare class DedupManager {
|
|
63
|
+
private readonly enabled;
|
|
64
|
+
private readonly maxEntries;
|
|
65
|
+
private readonly ttlMs;
|
|
66
|
+
private readonly adaptiveBounds;
|
|
67
|
+
private readonly sweepMs;
|
|
68
|
+
private readonly now;
|
|
69
|
+
private readonly trace;
|
|
70
|
+
private readonly seenMessageIds;
|
|
71
|
+
private sweepTimer;
|
|
72
|
+
private windowStartedAt;
|
|
73
|
+
private windowAccepted;
|
|
74
|
+
private suppressed;
|
|
75
|
+
private accepted;
|
|
76
|
+
constructor(options: DedupManagerOptions);
|
|
77
|
+
/** True when a publication carrying `messageId` was already seen. Records the
|
|
78
|
+
* ID and updates counters/trace on acceptance. Disabled or ID-less messages
|
|
79
|
+
* always pass through. */
|
|
80
|
+
isDuplicate(messageId: string, topic: string): boolean;
|
|
81
|
+
/** Start the periodic expiry sweep. No-op when disabled or no sweepMs was
|
|
82
|
+
* configured (the hot-path opportunistic expiry still bounds the map). */
|
|
83
|
+
start(): void;
|
|
84
|
+
/** Stop the periodic expiry sweep. */
|
|
85
|
+
stop(): void;
|
|
86
|
+
/** Return bounded deduplication counters for diagnostics and health checks. */
|
|
87
|
+
getStats(): DataBusDedupStats;
|
|
88
|
+
/** Drop all remembered IDs and reset dedup counters. */
|
|
89
|
+
reset(): void;
|
|
90
|
+
/** Remove IDs whose timestamp predates the effective TTL cutoff. */
|
|
91
|
+
private pruneExpired;
|
|
92
|
+
/** Effective TTL: the fixed `ttlMs` unless adaptive bounds are configured, in
|
|
93
|
+
* which case a higher recent message rate shortens the window (dedup only
|
|
94
|
+
* needs to live long enough to bridge duplicate bursts). The window resets
|
|
95
|
+
* every ADAPTIVE_WINDOW_MS. */
|
|
96
|
+
private currentTtl;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=dedup-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup-manager.d.ts","sourceRoot":"","sources":["../../src/core/dedup-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC;wBACoB;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9D,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,sEAAsE;IACtE,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,8DAA8D;IAC9D,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAQD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAK;gBAET,OAAO,EAAE,mBAAmB;IAWxC;;8BAE0B;IAC1B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAmCtD;8EAC0E;IAC1E,KAAK,IAAI,IAAI;IAKb,sCAAsC;IACtC,IAAI,IAAI,IAAI;IAKZ,+EAA+E;IAC/E,QAAQ,IAAI,iBAAiB;IAU7B,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAQb,oEAAoE;IACpE,OAAO,CAAC,YAAY;IAOpB;;;mCAG+B;IAC/B,OAAO,CAAC,UAAU;CAanB"}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* with custom adapters injected via `ClusterEnvironment`.
|
|
7
7
|
*/
|
|
8
8
|
import type { TabVisibilityState, WorkerClusterMessage } from './types';
|
|
9
|
+
import { CHANNEL_FALLBACK } from '../utils/constants';
|
|
10
|
+
import type { EVENT_TYPE } from '../utils/constants';
|
|
9
11
|
/** Minimal storage interface compatible with both localStorage and MemoryStorage. */
|
|
10
12
|
export interface StorageLike {
|
|
11
13
|
readonly length: number;
|
|
@@ -17,8 +19,8 @@ export interface StorageLike {
|
|
|
17
19
|
}
|
|
18
20
|
/** Minimal BroadcastChannel interface. The cluster uses it for control messages and event fan-out. */
|
|
19
21
|
export interface ClusterChannel {
|
|
20
|
-
addEventListener(type:
|
|
21
|
-
removeEventListener(type:
|
|
22
|
+
addEventListener(type: typeof EVENT_TYPE.MESSAGE, listener: (event: MessageEvent<WorkerClusterMessage>) => void): void;
|
|
23
|
+
removeEventListener(type: typeof EVENT_TYPE.MESSAGE, listener: (event: MessageEvent<WorkerClusterMessage>) => void): void;
|
|
22
24
|
postMessage(message: WorkerClusterMessage): void;
|
|
23
25
|
close(): void;
|
|
24
26
|
}
|
|
@@ -57,12 +59,50 @@ export interface ClusterEnvironment {
|
|
|
57
59
|
/** Remove a previously-added pageshow listener. */
|
|
58
60
|
removePageShowListener: (listener: () => void) => void;
|
|
59
61
|
}
|
|
62
|
+
/** Minimal window surface the storage-event channel needs (injectable for tests). */
|
|
63
|
+
export interface StorageEventWindow {
|
|
64
|
+
addEventListener(type: 'storage', listener: (event: {
|
|
65
|
+
key: string | null;
|
|
66
|
+
newValue: string | null;
|
|
67
|
+
}) => void): void;
|
|
68
|
+
removeEventListener(type: 'storage', listener: (event: {
|
|
69
|
+
key: string | null;
|
|
70
|
+
newValue: string | null;
|
|
71
|
+
}) => void): void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a {@link ClusterChannel} backed by localStorage `storage` events, as
|
|
75
|
+
* a coordination fallback for environments where BroadcastChannel is
|
|
76
|
+
* unavailable. Returns null when localStorage or a storage-event source is
|
|
77
|
+
* missing.
|
|
78
|
+
*
|
|
79
|
+
* Semantics mirror BroadcastChannel: writes are not echoed to the sender
|
|
80
|
+
* (per spec, the writing tab receives no `storage` event) and every message
|
|
81
|
+
* is JSON-serializable. The payload is written under a dedicated key and
|
|
82
|
+
* removed on close.
|
|
83
|
+
*
|
|
84
|
+
* Security note: unlike BroadcastChannel messages (memory only), these
|
|
85
|
+
* payloads transit through localStorage and therefore persist — at least
|
|
86
|
+
* transiently, and after a crash indefinitely. Coordination frames carry
|
|
87
|
+
* plaintext topic names; callers who enable this fallback accept that
|
|
88
|
+
* trade-off (see docs/configuration.md).
|
|
89
|
+
*/
|
|
90
|
+
export declare function createStorageEventChannel(options: {
|
|
91
|
+
name: string;
|
|
92
|
+
storage: StorageLike | null;
|
|
93
|
+
win: StorageEventWindow | null;
|
|
94
|
+
}): ClusterChannel | null;
|
|
60
95
|
/**
|
|
61
96
|
* Default environment adapter for browser runtimes.
|
|
62
97
|
* Probes for localStorage, BroadcastChannel, document, and window APIs
|
|
63
98
|
* and gracefully returns null / no-ops when they are absent (SSR, Node).
|
|
64
99
|
*/
|
|
65
|
-
export declare function createBrowserEnvironment(
|
|
100
|
+
export declare function createBrowserEnvironment(options?: {
|
|
101
|
+
/** When BroadcastChannel is unavailable, fall back to a localStorage
|
|
102
|
+
* storage-event channel instead of degrading to local mode. Opt-in because
|
|
103
|
+
* the fallback persists coordination payloads in localStorage. */
|
|
104
|
+
channelFallback?: (typeof CHANNEL_FALLBACK)[keyof typeof CHANNEL_FALLBACK];
|
|
105
|
+
}): ClusterEnvironment;
|
|
66
106
|
/**
|
|
67
107
|
* Probe a storage instance with a write-read-delete round-trip.
|
|
68
108
|
* Returns a type guard so the caller can narrow the type after a successful check.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { DataBusReplayPersistence } from './replay-persistence';
|
|
2
|
+
import type { DataBusTraceReporter } from './trace';
|
|
3
|
+
import type { DataBusMessage, DataBusMessageHandler } from './types';
|
|
4
|
+
import { PRUNE_STRATEGY } from '../utils/constants';
|
|
5
|
+
/** Thrown when a lifecycle transition cancels an in-flight persistence retry. */
|
|
6
|
+
export declare class PersistenceRetryCancelledError extends Error {
|
|
7
|
+
constructor();
|
|
8
|
+
}
|
|
9
|
+
/** Resolved constructor options after the DataBus applies defaults. */
|
|
10
|
+
export interface ReplayManagerDeps<TData = unknown> {
|
|
11
|
+
/** Whether replay buffering is enabled at all (false → no-op instance). */
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
/** Maximum buffered publications per topic. */
|
|
14
|
+
maxPerTopic: number;
|
|
15
|
+
/** Optional durable history backend; null → in-memory only. */
|
|
16
|
+
persistence?: DataBusReplayPersistence<TData> | null;
|
|
17
|
+
/** Optional producer-timestamp retention window in milliseconds. */
|
|
18
|
+
retentionMs?: number | undefined;
|
|
19
|
+
/** History trimming policy. */
|
|
20
|
+
pruneStrategy: (typeof PRUNE_STRATEGY)[keyof typeof PRUNE_STRATEGY];
|
|
21
|
+
/** Optional periodic sweep interval for durable retention cleanup. */
|
|
22
|
+
retentionSweepMs?: number | undefined;
|
|
23
|
+
/** Total persistence attempts including the initial operation. */
|
|
24
|
+
persistenceRetryMaxAttempts: number;
|
|
25
|
+
/** Initial delay between persistence retry attempts. */
|
|
26
|
+
persistenceRetryBackoffMs: number;
|
|
27
|
+
/** Injectable epoch clock; used for retention cutoffs. */
|
|
28
|
+
now: () => number;
|
|
29
|
+
/** Trace sink for persistence retry/cleanup diagnostics. */
|
|
30
|
+
trace: DataBusTraceReporter;
|
|
31
|
+
/** Sink for persistence failures (routes to the DataBus failure ledger). */
|
|
32
|
+
onPersistenceError: (error: unknown) => void;
|
|
33
|
+
/** Sink for a throwing replay-delivery handler (dispatch error source). */
|
|
34
|
+
onDispatchError: (error: unknown) => void;
|
|
35
|
+
}
|
|
36
|
+
export declare class ReplayManager<TData = unknown> {
|
|
37
|
+
private readonly deps;
|
|
38
|
+
private readonly buffers;
|
|
39
|
+
private readonly maxPerTopic;
|
|
40
|
+
private readonly persistence;
|
|
41
|
+
private readonly retentionMs;
|
|
42
|
+
private readonly pruneStrategy;
|
|
43
|
+
private readonly retentionSweepMs;
|
|
44
|
+
private readonly persistenceRetryMaxAttempts;
|
|
45
|
+
private readonly persistenceRetryBackoffMs;
|
|
46
|
+
private readonly now;
|
|
47
|
+
private readonly trace;
|
|
48
|
+
private readonly onPersistenceError;
|
|
49
|
+
private readonly onDispatchError;
|
|
50
|
+
/** Bumped on suspend/stop so in-flight persistence retries are cancelled. */
|
|
51
|
+
private retryGeneration;
|
|
52
|
+
private pendingReplayPersistence;
|
|
53
|
+
private persistenceFlushScheduled;
|
|
54
|
+
private readonly hydration;
|
|
55
|
+
/** Coalesced retention cleanup: the newest cutoff wins while one is running. */
|
|
56
|
+
private retentionCleanup;
|
|
57
|
+
private retentionCutoff;
|
|
58
|
+
private retentionTimer;
|
|
59
|
+
constructor(deps: ReplayManagerDeps<TData>);
|
|
60
|
+
/** True when replay buffering is enabled. */
|
|
61
|
+
get enabled(): boolean;
|
|
62
|
+
/** Append a dispatched publication to the topic's replay ring buffer.
|
|
63
|
+
* No-op when replay is disabled. */
|
|
64
|
+
record(message: DataBusMessage<TData>): void;
|
|
65
|
+
/** Deliver buffered history to a newly-registered handler. For an exact
|
|
66
|
+
* topic this is that topic's ring; for a wildcard subscription every
|
|
67
|
+
* buffered topic matching the pattern contributes (in buffer insertion
|
|
68
|
+
* order). Replay deliveries are marked `replayed: true` and are not counted
|
|
69
|
+
* into trace metrics.
|
|
70
|
+
*
|
|
71
|
+
* When a durable persistence backend is present, delivery waits for the
|
|
72
|
+
* hydration load to settle first; `isHandlerActive` is then consulted so a
|
|
73
|
+
* handler that unsubscribed during the async load does not receive history.
|
|
74
|
+
*/
|
|
75
|
+
deliverReplay(topic: string, replayOption: boolean | number, handler: DataBusMessageHandler<TData>, isHandlerActive?: () => boolean): void;
|
|
76
|
+
/** Clean up a topic that lost its last local handler: drop the ring buffer,
|
|
77
|
+
* filter queued batch flushes (so an in-flight append cannot undo the
|
|
78
|
+
* clearTopic), and prune durable history. */
|
|
79
|
+
onTopicUnsubscribed(topic: string): void;
|
|
80
|
+
/** Clear all in-memory replay buffers and, when supported, durable history.
|
|
81
|
+
* Reports persistence failures and rethrows, mirroring the public API
|
|
82
|
+
* contract that callers can observe a failed clear. */
|
|
83
|
+
clearAll(): Promise<void>;
|
|
84
|
+
/** Clear replay history for one exact topic, including durable storage. */
|
|
85
|
+
clearTopic(topic: string): Promise<void>;
|
|
86
|
+
/** Remove replay entries older than an epoch-millisecond cutoff. */
|
|
87
|
+
clearBefore(timestamp: number): Promise<void>;
|
|
88
|
+
/** Start the periodic retention sweep. No-op when no durable retention
|
|
89
|
+
* config makes it necessary. */
|
|
90
|
+
start(): void;
|
|
91
|
+
/** Stop the periodic retention sweep. */
|
|
92
|
+
stop(): void;
|
|
93
|
+
/** Suspend the manager: cancel in-flight persistence retries (so a hidden tab
|
|
94
|
+
* or stopped bus does not keep hammering the store) and stop the sweep. */
|
|
95
|
+
suspend(): void;
|
|
96
|
+
/** Drop all in-memory buffers (used on full teardown). */
|
|
97
|
+
resetBuffers(): void;
|
|
98
|
+
/** Buffer occupancy for diagnostics. `bytes` is an approximate in-memory
|
|
99
|
+
* payload footprint (same heuristic as adaptive load weighting), computed on
|
|
100
|
+
* demand so the hot append path never pays for it. */
|
|
101
|
+
getStats(): {
|
|
102
|
+
enabled: boolean;
|
|
103
|
+
topics: number;
|
|
104
|
+
messages: number;
|
|
105
|
+
bytes: number;
|
|
106
|
+
};
|
|
107
|
+
/** Deliver history from one topic's ring to a handler, isolating a throwing
|
|
108
|
+
* handler so the remaining buffers are still delivered. */
|
|
109
|
+
private deliver;
|
|
110
|
+
/** Coalesce queued persistence appends into a single microtask batch so a
|
|
111
|
+
* burst of publications does not issue one IndexedDB transaction each.
|
|
112
|
+
* Only reachable when the backend advertises `appendBatch` (the sole queuer,
|
|
113
|
+
* `record()`, guards on it), so the batched path is unconditional here. */
|
|
114
|
+
private schedulePersistenceFlush;
|
|
115
|
+
/** Load durable history into the in-memory rings once at startup, pruning
|
|
116
|
+
* entries past the retention window first. Failures are reported but do not
|
|
117
|
+
* block startup — the bus runs with whatever survived. */
|
|
118
|
+
private hydrate;
|
|
119
|
+
/** Coalesce retention cleanup: the newest cutoff wins while one pass runs,
|
|
120
|
+
* so a burst of publications issues at most one clearBefore transaction. */
|
|
121
|
+
private scheduleRetentionCleanup;
|
|
122
|
+
/** Run a persistence operation with exponential backoff on transient failure.
|
|
123
|
+
* Bumped `retryGeneration` (suspend/stop) cancels the loop early; a
|
|
124
|
+
* structurally failing operation throws after `persistenceRetryMaxAttempts`,
|
|
125
|
+
* leaving the ring buffer intact so the bus keeps working. */
|
|
126
|
+
private withPersistenceRetry;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=replay-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-manager.d.ts","sourceRoot":"","sources":["../../src/core/replay-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { DataBusMessage } from './types';
|
|
2
|
+
import { PRUNE_STRATEGY } from '../utils/constants';
|
|
2
3
|
/** Optional persistence backend for replay history. */
|
|
3
4
|
export interface DataBusReplayPersistence<TData = unknown> {
|
|
4
5
|
load(): Promise<ReadonlyArray<DataBusMessage<TData>>>;
|
|
5
6
|
append(message: DataBusMessage<TData>): Promise<void>;
|
|
7
|
+
/** Optional bulk append used to amortize IndexedDB transaction overhead. */
|
|
8
|
+
appendBatch?(messages: ReadonlyArray<DataBusMessage<TData>>): Promise<void>;
|
|
6
9
|
/** Remove all persisted replay history. */
|
|
7
10
|
clear?(): Promise<void>;
|
|
8
11
|
/** Remove persisted replay history for one exact topic. */
|
|
@@ -13,7 +16,7 @@ export interface DataBusReplayPersistence<TData = unknown> {
|
|
|
13
16
|
export interface IndexedDbReplayPersistenceOptions {
|
|
14
17
|
dbName?: string;
|
|
15
18
|
maxPerTopic: number;
|
|
16
|
-
pruneStrategy?:
|
|
19
|
+
pruneStrategy?: (typeof PRUNE_STRATEGY)[keyof typeof PRUNE_STRATEGY];
|
|
17
20
|
retentionMs?: number;
|
|
18
21
|
}
|
|
19
22
|
/** Create a browser IndexedDB-backed replay store. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-persistence.d.ts","sourceRoot":"","sources":["../../src/core/replay-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"replay-persistence.d.ts","sourceRoot":"","sources":["../../src/core/replay-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAA0B,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG5E,uDAAuD;AACvD,MAAM,WAAW,wBAAwB,CAAC,KAAK,GAAG,OAAO;IACvD,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,4EAA4E;IAC5E,WAAW,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,2CAA2C;IAC3C,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,2DAA2D;IAC3D,UAAU,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,+EAA+E;IAC/E,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,iCAAiC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,sDAAsD;AACtD,wBAAgB,gCAAgC,CAAC,KAAK,GAAG,OAAO,EAC9D,OAAO,EAAE,iCAAiC,GACzC,wBAAwB,CAAC,KAAK,CAAC,CA4PjC"}
|
package/dist/core/routing.d.ts
CHANGED
|
@@ -5,19 +5,38 @@
|
|
|
5
5
|
* owner, and decide when to migrate a topic. All side-effect-free, making
|
|
6
6
|
* them straightforward to test and reason about.
|
|
7
7
|
*/
|
|
8
|
-
import type { WorkerRecord, WorkerRoute } from './types';
|
|
8
|
+
import type { LoadWeightingOptions, WorkerRecord, WorkerRoute } from './types';
|
|
9
9
|
/** Default cap on the number of Workers that can own topics concurrently.
|
|
10
10
|
* Limits fan-out breadth: only N workers are eligible to be new-route
|
|
11
11
|
* owners, so a cluster of 20 tabs still concentrates ownership on a few. */
|
|
12
12
|
export declare const DEFAULT_MAX_ACTIVE_WORKERS = 3;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Compute the effective load score used for owner selection.
|
|
15
|
+
*
|
|
16
|
+
* Legacy behavior: `worker.load` (owned-topic count) with no throughput
|
|
17
|
+
* contribution. When a Worker publishes a traffic sample AND weights are set,
|
|
18
|
+
* the normalized per-second rates are added on top, so a busy owner becomes
|
|
19
|
+
* less attractive for NEW routes without ever migrating an existing one.
|
|
20
|
+
* Returns the raw topic count when no sample or no weight is present.
|
|
21
|
+
*/
|
|
22
|
+
export declare function effectiveWorkerLoad(worker: WorkerRecord, options?: LoadWeightingOptions): number;
|
|
23
|
+
/**
|
|
24
|
+
* Cheap, allocation-free estimate of a payload's wire size, used to populate
|
|
25
|
+
* the byte side of an adaptive load sample. Only runs when adaptive routing is
|
|
26
|
+
* enabled, so approximate sizes are fine — the goal is a stable cross-worker
|
|
27
|
+
* comparison, not an exact byte count. Sizes: null/undefined 0, booleans 4,
|
|
28
|
+
* numbers 8, strings their length, binary views their byteLength, arrays an
|
|
29
|
+
* 8-byte header plus elements, plain objects the sum of their values.
|
|
30
|
+
*/
|
|
31
|
+
export declare function approximatePayloadBytes(payload: unknown): number;
|
|
32
|
+
/**
|
|
33
|
+
* Pick the Worker with the fewest effective load, optionally preferring a
|
|
15
34
|
* specific sticky owner when it is still in the candidate set.
|
|
16
35
|
* Uses a single reduce pass instead of a full sort — O(n) — and breaks
|
|
17
36
|
* load ties by workerId for deterministic routing across tabs (the
|
|
18
37
|
* comparison is code-unit based, not locale-based, for cross-host stability).
|
|
19
38
|
*/
|
|
20
|
-
export declare function selectLeastLoadedWorker(workers: readonly WorkerRecord[], preferredWorkerId?: string): WorkerRecord | undefined;
|
|
39
|
+
export declare function selectLeastLoadedWorker(workers: readonly WorkerRecord[], preferredWorkerId?: string, options?: LoadWeightingOptions): WorkerRecord | undefined;
|
|
21
40
|
/**
|
|
22
41
|
* Select the (up to `maxActiveWorkers`) Workers eligible to own topics.
|
|
23
42
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/core/routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/core/routing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG/E;;4EAE4E;AAC5E,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,MAAM,CA2CR;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEhE;AA4CD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,iBAAiB,CAAC,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,YAAY,GAAG,SAAS,CAY1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,gBAAgB,SAA6B,GAC5C,YAAY,EAAE,CAchB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,eAAe,EAAE,MAAM,GACtB,YAAY,GAAG,IAAI,CAYrB;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAEnG;AAED;;oDAEoD;AACpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;sCAGsC;AACtC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAM3E"}
|
|
@@ -6,10 +6,6 @@
|
|
|
6
6
|
* on quota/failure. Keeps the coordination metadata writes off the hot path.
|
|
7
7
|
*/
|
|
8
8
|
import type { StorageLike } from './environment';
|
|
9
|
-
/**
|
|
10
|
-
* Coalesces synchronous storage writes and applies them in one pass, with
|
|
11
|
-
* exponential backoff when the underlying storage rejects a write.
|
|
12
|
-
*/
|
|
13
9
|
/**
|
|
14
10
|
* Coalesces synchronous storage writes and applies them in one pass, with
|
|
15
11
|
* exponential backoff when the underlying storage rejects a write.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAajD;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IAS3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,YAAY,CAA0B;gBAEjB,OAAO,EAAE,WAAW;IAEjD;;gCAE4B;IAC5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAab,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzC,KAAK,IAAI,IAAI;IA6Cb,yEAAyE;IACzE,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;CAMpB"}
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -7,35 +7,38 @@
|
|
|
7
7
|
* message path — errors in the sink are isolated to console.warn.
|
|
8
8
|
*/
|
|
9
9
|
import type { WorkerStatus } from './types';
|
|
10
|
+
import type { PERSISTENCE_OPERATION, RECOVERY_OUTCOME, RELIABILITY_OPERATION, SUBSCRIPTION_ACTION, TRACE_ERROR_SOURCE, TRACE_LIFECYCLE_ACTION } from '../utils/constants';
|
|
11
|
+
import { TRACE_EVENT_TYPE, TRACE_MODE } from '../utils/constants';
|
|
10
12
|
/** Trace reporting mode: record only events, only metrics, or both. */
|
|
11
13
|
/** Selects which trace categories the reporter emits.
|
|
12
14
|
* - `events` — lifecycle/status/subscription/coordination/error events only.
|
|
13
15
|
* - `metrics` — periodic `message_metrics` snapshots only.
|
|
14
16
|
* - `all` — both event streams and metrics snapshots. */
|
|
15
|
-
export type DataBusTraceMode =
|
|
17
|
+
export type DataBusTraceMode = (typeof TRACE_MODE)[keyof typeof TRACE_MODE];
|
|
16
18
|
/** Emitted when the DataBus starts, stops, suspends, or resumes. */
|
|
17
19
|
export interface DataBusLifecycleTraceEvent {
|
|
18
|
-
type:
|
|
19
|
-
action:
|
|
20
|
+
type: typeof TRACE_EVENT_TYPE.LIFECYCLE;
|
|
21
|
+
action: (typeof TRACE_LIFECYCLE_ACTION)[keyof typeof TRACE_LIFECYCLE_ACTION];
|
|
20
22
|
timestamp: number;
|
|
21
23
|
}
|
|
22
24
|
/** Emitted when the transport connection status changes. */
|
|
23
25
|
export interface DataBusStatusTraceEvent {
|
|
24
|
-
type:
|
|
26
|
+
type: typeof TRACE_EVENT_TYPE.STATUS;
|
|
25
27
|
status: WorkerStatus;
|
|
26
28
|
timestamp: number;
|
|
27
29
|
}
|
|
28
30
|
/** Emitted when a topic subscription is added or removed. */
|
|
29
31
|
export interface DataBusSubscriptionTraceEvent {
|
|
30
|
-
type:
|
|
31
|
-
action:
|
|
32
|
+
type: typeof TRACE_EVENT_TYPE.SUBSCRIPTION;
|
|
33
|
+
action: (typeof SUBSCRIPTION_ACTION)[keyof typeof SUBSCRIPTION_ACTION];
|
|
32
34
|
topic: string;
|
|
33
35
|
activeTopics: number;
|
|
34
36
|
timestamp: number;
|
|
35
37
|
}
|
|
36
|
-
/** Emitted
|
|
38
|
+
/** Emitted after each transport open (initial start and recovery) to record
|
|
39
|
+
* the coordinated cluster state, including the settled route list. */
|
|
37
40
|
export interface DataBusCoordinationTraceEvent {
|
|
38
|
-
type:
|
|
41
|
+
type: typeof TRACE_EVENT_TYPE.COORDINATION;
|
|
39
42
|
coordinated: boolean;
|
|
40
43
|
activeWorkers: number;
|
|
41
44
|
workers: string[];
|
|
@@ -44,19 +47,19 @@ export interface DataBusCoordinationTraceEvent {
|
|
|
44
47
|
}
|
|
45
48
|
/** Emitted when a transport or operation error occurs. */
|
|
46
49
|
export interface DataBusErrorTraceEvent {
|
|
47
|
-
type:
|
|
48
|
-
source:
|
|
50
|
+
type: typeof TRACE_EVENT_TYPE.ERROR;
|
|
51
|
+
source: (typeof TRACE_ERROR_SOURCE)[keyof typeof TRACE_ERROR_SOURCE];
|
|
49
52
|
timestamp: number;
|
|
50
53
|
}
|
|
51
54
|
/** Bounded reliability diagnostics for recovery, acknowledgments, and migrations. */
|
|
52
55
|
export interface DataBusReliabilityTraceEvent {
|
|
53
|
-
type:
|
|
54
|
-
operation:
|
|
56
|
+
type: typeof TRACE_EVENT_TYPE.RELIABILITY;
|
|
57
|
+
operation: (typeof RELIABILITY_OPERATION)[keyof typeof RELIABILITY_OPERATION];
|
|
55
58
|
topic?: string;
|
|
56
|
-
persistenceOperation?:
|
|
59
|
+
persistenceOperation?: (typeof PERSISTENCE_OPERATION)[keyof typeof PERSISTENCE_OPERATION];
|
|
57
60
|
attempt?: number;
|
|
58
61
|
/** Outcome for a transport recovery attempt. */
|
|
59
|
-
outcome?:
|
|
62
|
+
outcome?: (typeof RECOVERY_OUTCOME)[keyof typeof RECOVERY_OUTCOME];
|
|
60
63
|
durationMs?: number;
|
|
61
64
|
timestamp: number;
|
|
62
65
|
}
|
|
@@ -66,7 +69,7 @@ export interface DataBusReliabilityTraceEvent {
|
|
|
66
69
|
* `metricsIntervalMs`.
|
|
67
70
|
*/
|
|
68
71
|
export interface DataBusMetricsTraceEvent {
|
|
69
|
-
type:
|
|
72
|
+
type: typeof TRACE_EVENT_TYPE.MESSAGE_METRICS;
|
|
70
73
|
durationMs: number;
|
|
71
74
|
received: number;
|
|
72
75
|
dispatched: number;
|
|
@@ -80,6 +83,31 @@ export interface DataBusMetricsTraceEvent {
|
|
|
80
83
|
dedupSuppressed: number;
|
|
81
84
|
timestamp: number;
|
|
82
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Synchronous metrics snapshot: same derived counters as a periodic
|
|
88
|
+
* `message_metrics` event, but queryable on demand (e.g. from
|
|
89
|
+
* `getDiagnostics()`) without a sink or an interval flush, and without
|
|
90
|
+
* resetting the aggregation window.
|
|
91
|
+
*/
|
|
92
|
+
export interface DataBusMetricsSnapshot {
|
|
93
|
+
/** Milliseconds elapsed in the current aggregation window. */
|
|
94
|
+
durationMs: number;
|
|
95
|
+
/** Messages received in the window. */
|
|
96
|
+
received: number;
|
|
97
|
+
/** Messages dispatched locally in the window. */
|
|
98
|
+
dispatched: number;
|
|
99
|
+
/** Distinct topics touched in the window. */
|
|
100
|
+
topics: number;
|
|
101
|
+
/** Latency samples collected in the window. */
|
|
102
|
+
dispatchSamples: number;
|
|
103
|
+
dispatchAvgMs: number;
|
|
104
|
+
dispatchP50Ms: number;
|
|
105
|
+
dispatchP95Ms: number;
|
|
106
|
+
dispatchMaxMs: number;
|
|
107
|
+
dedupAccepted: number;
|
|
108
|
+
dedupSuppressed: number;
|
|
109
|
+
timestamp: number;
|
|
110
|
+
}
|
|
83
111
|
export type DataBusTraceEvent = DataBusLifecycleTraceEvent | DataBusStatusTraceEvent | DataBusSubscriptionTraceEvent | DataBusCoordinationTraceEvent | DataBusErrorTraceEvent | DataBusReliabilityTraceEvent | DataBusMetricsTraceEvent;
|
|
84
112
|
/** Distributive-conditional type: given a trace event union, derive the same shape minus `timestamp`. */
|
|
85
113
|
type DataBusTraceEventInput = DataBusTraceEvent extends infer TEvent ? TEvent extends DataBusTraceEvent ? Omit<TEvent, 'timestamp'> : never : never;
|
|
@@ -134,8 +162,20 @@ export declare class DataBusTraceReporter {
|
|
|
134
162
|
/** Pause the metrics interval and reset accumulated counters. */
|
|
135
163
|
pause(): void;
|
|
136
164
|
stop(): void;
|
|
165
|
+
/** Synchronous sink state for diagnostics: whether delivery is async and how
|
|
166
|
+
* many events are queued behind the microtask flush. A growing queue under
|
|
167
|
+
* `asyncSink: true` is the first sign of sink back-pressure. */
|
|
168
|
+
getSinkState(): {
|
|
169
|
+
asyncSink: boolean;
|
|
170
|
+
pendingEvents: number;
|
|
171
|
+
};
|
|
137
172
|
/** Record an instantaneous trace event (lifecycle, status, error, etc.). */
|
|
138
173
|
event(event: DataBusTraceEventInput): void;
|
|
174
|
+
/** Synchronous snapshot of the current metrics window without resetting it.
|
|
175
|
+
* Returns the same derived counters as a periodic `message_metrics` event,
|
|
176
|
+
* or null when metrics recording is inactive (disabled or events-only mode).
|
|
177
|
+
* The window keeps accumulating until the next interval flush. */
|
|
178
|
+
getMetrics(): DataBusMetricsSnapshot | null;
|
|
139
179
|
/** Record that a message was received on `topic`; stores its timestamp for latency tracking. */
|
|
140
180
|
recordReceived(topic: string): void;
|
|
141
181
|
/**
|
package/dist/core/trace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"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"}
|