@catalyst-cloud/sdk 0.16.0 → 0.16.1
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/dist/events-socket.d.ts +82 -0
- package/dist/events-socket.d.ts.map +1 -0
- package/dist/events-socket.js +295 -0
- package/dist/events-socket.js.map +1 -0
- package/dist/events.d.ts +38 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +161 -3
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/machine-inventory.d.ts +33 -0
- package/dist/machine-inventory.d.ts.map +1 -0
- package/dist/machine-inventory.js +38 -0
- package/dist/machine-inventory.js.map +1 -0
- package/dist/tenant-client.d.ts +41 -0
- package/dist/tenant-client.d.ts.map +1 -1
- package/dist/tenant-client.js +6 -0
- package/dist/tenant-client.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type AuthStrategy, type WebSocketFactory } from "./live-sync-client.js";
|
|
2
|
+
/** One `events` frame as the cloud sent it. `events` is unparsed: the follower validates each one. */
|
|
3
|
+
export interface EventsFrame {
|
|
4
|
+
after: number;
|
|
5
|
+
through: number;
|
|
6
|
+
gap: boolean;
|
|
7
|
+
events: unknown[];
|
|
8
|
+
}
|
|
9
|
+
export type EventsSocketState = "idle" | "connecting" | "live" | "down" | "stopped";
|
|
10
|
+
export interface EventsSocketOptions {
|
|
11
|
+
/** The cloud origin, e.g. `https://staging.catalystcloud.dev` (no `/api/v1`). */
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
auth: Exclude<AuthStrategy, {
|
|
14
|
+
kind: "cookie";
|
|
15
|
+
}>;
|
|
16
|
+
tenantId: string;
|
|
17
|
+
/** Opens the socket. Defaults to the runtime's global `WebSocket`. */
|
|
18
|
+
wsFactory?: WebSocketFactory;
|
|
19
|
+
/** Silence after which the client sends a ping. Default 90 s. */
|
|
20
|
+
pingAfterMs?: number;
|
|
21
|
+
/** How long a ping, or a new socket's subscription, may go unanswered before reconnecting. Default 15 s. */
|
|
22
|
+
pongTimeoutMs?: number;
|
|
23
|
+
/** First reconnect delay after a failure, doubling to `reconnectMaxMs`. Default 1 s. */
|
|
24
|
+
reconnectMinMs?: number;
|
|
25
|
+
reconnectMaxMs?: number;
|
|
26
|
+
/** Buffered frames past this count, or past `maxBufferedBytes`, are dropped and reported as an overflow. */
|
|
27
|
+
maxBufferedFrames?: number;
|
|
28
|
+
maxBufferedBytes?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface EventsSocketBatch {
|
|
31
|
+
frames: EventsFrame[];
|
|
32
|
+
/** Frames were dropped since the last take; the follower must catch up through the backbone. */
|
|
33
|
+
overflowed: boolean;
|
|
34
|
+
/** The generation the frames were taken under. */
|
|
35
|
+
generation: number;
|
|
36
|
+
}
|
|
37
|
+
/** The runtime's global WebSocket, or null when it has none (then a follower polls). */
|
|
38
|
+
export declare function globalWebSocketFactory(): WebSocketFactory | null;
|
|
39
|
+
/** The events socket URL. The token rides `?token=` because a WebSocket cannot set a header. */
|
|
40
|
+
export declare function eventsSocketUrl(options: Pick<EventsSocketOptions, "baseUrl" | "auth" | "tenantId">, token?: string): string;
|
|
41
|
+
export declare class EventsChannelClient {
|
|
42
|
+
private readonly options;
|
|
43
|
+
private readonly factory;
|
|
44
|
+
private ws;
|
|
45
|
+
private current;
|
|
46
|
+
private gen;
|
|
47
|
+
private frames;
|
|
48
|
+
private bufferedBytes;
|
|
49
|
+
private overflow;
|
|
50
|
+
private backoff;
|
|
51
|
+
private openedAt;
|
|
52
|
+
/** Bumped on every teardown, so a bearer token resolving late cannot open a superseded socket. */
|
|
53
|
+
private attempt;
|
|
54
|
+
private reconnectTimer;
|
|
55
|
+
private silenceTimer;
|
|
56
|
+
private answerTimer;
|
|
57
|
+
private waiters;
|
|
58
|
+
constructor(options: EventsSocketOptions);
|
|
59
|
+
get state(): EventsSocketState;
|
|
60
|
+
/** Bumped each time a socket confirms its subscription. */
|
|
61
|
+
get generation(): number;
|
|
62
|
+
hasPending(): boolean;
|
|
63
|
+
/** Take every buffered frame, and whether any were dropped, in arrival order. */
|
|
64
|
+
take(): EventsSocketBatch;
|
|
65
|
+
/**
|
|
66
|
+
* Resolves on the next buffered frame or the next time a socket goes live. Never rejects; an abort
|
|
67
|
+
* only unregisters the waiter, so a long outage does not pile them up.
|
|
68
|
+
*/
|
|
69
|
+
changed(signal?: AbortSignal): Promise<void>;
|
|
70
|
+
start(): void;
|
|
71
|
+
stop(): void;
|
|
72
|
+
private notify;
|
|
73
|
+
private open;
|
|
74
|
+
private onMessage;
|
|
75
|
+
/** The socket closed or failed: tear it down and schedule the next attempt. */
|
|
76
|
+
private fail;
|
|
77
|
+
private teardown;
|
|
78
|
+
private armSilence;
|
|
79
|
+
private armAnswer;
|
|
80
|
+
private clearAnswer;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=events-socket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-socket.d.ts","sourceRoot":"","sources":["../src/events-socket.ts"],"names":[],"mappings":"AAeA,OAAO,EAAmB,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAsB,MAAM,uBAAuB,CAAC;AAGtH,sGAAsG;AACtG,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEpF,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4GAA4G;IAC5G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4GAA4G;IAC5G,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,gGAAgG;IAChG,UAAU,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD,wFAAwF;AACxF,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,IAAI,CAGhE;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAS3H;AAmBD,qBAAa,mBAAmB;IAiBlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,EAAE,CAA8B;IACxC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,kGAAkG;IAClG,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,OAAO,CAAyB;gBAEX,OAAO,EAAE,mBAAmB;IAOzD,IAAI,KAAK,IAAI,iBAAiB,CAE7B;IAED,2DAA2D;IAC3D,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,UAAU,IAAI,OAAO;IAIrB,iFAAiF;IACjF,IAAI,IAAI,iBAAiB;IAQzB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5C,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,MAAM;YAMA,IAAI;IA6BlB,OAAO,CAAC,SAAS;IA2CjB,+EAA+E;IAC/E,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,QAAQ;IA4BhB,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// events-socket.ts — CTC-5295. The client half of the events socket (`/api/v1/connect?channels=events`,
|
|
2
|
+
// catalyst-cloud CTC-4562): the tenant pushes every backbone event over a hibernatable WebSocket, so
|
|
3
|
+
// an event follower hears about an event when it happens instead of polling `/events/backbone`.
|
|
4
|
+
//
|
|
5
|
+
// This class only carries frames. It opens the socket, buffers each `events` frame, keeps the socket
|
|
6
|
+
// alive, and reconnects. Deciding what a frame means for the cache (apply it, or catch up through the
|
|
7
|
+
// backbone first) is `CatalystEventSync`'s job, in events.ts.
|
|
8
|
+
//
|
|
9
|
+
// ⭐ THE FRAME. `{type:"events", after, through, events[], gap?}`. Every backbone sequence in
|
|
10
|
+
// (after, through] was scanned for this socket, and on an unfiltered `fields=full` socket the events
|
|
11
|
+
// listed are all of them, as backbone lines. The next frame's `after` is this frame's `through`.
|
|
12
|
+
//
|
|
13
|
+
// ⭐ GENERATION. Bumped each time a socket confirms its subscription (the `channels` frame). Frames
|
|
14
|
+
// from before a reconnect stay buffered (they are real events), but the follower must catch up
|
|
15
|
+
// through the backbone once per generation, because nothing was pushed while the socket was down.
|
|
16
|
+
import { buildConnectUrl } from "./live-sync-client.js";
|
|
17
|
+
import { PING_FRAME, PONG_FRAME } from "./types.js";
|
|
18
|
+
const DEFAULT_PING_AFTER_MS = 90_000;
|
|
19
|
+
const DEFAULT_PONG_TIMEOUT_MS = 15_000;
|
|
20
|
+
const DEFAULT_RECONNECT_MIN_MS = 1_000;
|
|
21
|
+
const DEFAULT_RECONNECT_MAX_MS = 30_000;
|
|
22
|
+
const DEFAULT_MAX_BUFFERED_FRAMES = 1_000;
|
|
23
|
+
const DEFAULT_MAX_BUFFERED_BYTES = 8 * 1024 * 1024;
|
|
24
|
+
/** The mirror's reauthenticate close codes: the credential bound passed, so reconnect at once. */
|
|
25
|
+
const REAUTH_CLOSE_CODES = new Set([4401, 4410]);
|
|
26
|
+
/** A socket that lived shorter than this before a reauth close reconnects with backoff, not at once. */
|
|
27
|
+
const MIN_HEALTHY_LIFETIME_MS = 1_000;
|
|
28
|
+
/** The runtime's global WebSocket, or null when it has none (then a follower polls). */
|
|
29
|
+
export function globalWebSocketFactory() {
|
|
30
|
+
const Ctor = globalThis.WebSocket;
|
|
31
|
+
return typeof Ctor === "function" ? (url) => new Ctor(url) : null;
|
|
32
|
+
}
|
|
33
|
+
/** The events socket URL. The token rides `?token=` because a WebSocket cannot set a header. */
|
|
34
|
+
export function eventsSocketUrl(options, token) {
|
|
35
|
+
return buildConnectUrl({
|
|
36
|
+
baseUrl: options.baseUrl,
|
|
37
|
+
connectPath: "/api/v1/connect",
|
|
38
|
+
accountId: options.tenantId,
|
|
39
|
+
auth: options.auth,
|
|
40
|
+
...(token !== undefined ? { bearerToken: token } : {}),
|
|
41
|
+
extraParams: { channels: "events", fields: "full" },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function closeCode(event) {
|
|
45
|
+
const code = event?.code;
|
|
46
|
+
return typeof code === "number" ? code : undefined;
|
|
47
|
+
}
|
|
48
|
+
function parseEventsFrame(value) {
|
|
49
|
+
const { after, through, events } = value;
|
|
50
|
+
if (!Number.isSafeInteger(after) ||
|
|
51
|
+
!Number.isSafeInteger(through) ||
|
|
52
|
+
through < after ||
|
|
53
|
+
!Array.isArray(events))
|
|
54
|
+
return null;
|
|
55
|
+
return { after: after, through: through, gap: value.gap === true, events };
|
|
56
|
+
}
|
|
57
|
+
export class EventsChannelClient {
|
|
58
|
+
options;
|
|
59
|
+
factory;
|
|
60
|
+
ws = null;
|
|
61
|
+
current = "idle";
|
|
62
|
+
gen = 0;
|
|
63
|
+
frames = [];
|
|
64
|
+
bufferedBytes = 0;
|
|
65
|
+
overflow = false;
|
|
66
|
+
backoff;
|
|
67
|
+
openedAt = 0;
|
|
68
|
+
/** Bumped on every teardown, so a bearer token resolving late cannot open a superseded socket. */
|
|
69
|
+
attempt = 0;
|
|
70
|
+
reconnectTimer = null;
|
|
71
|
+
silenceTimer = null;
|
|
72
|
+
answerTimer = null;
|
|
73
|
+
waiters = [];
|
|
74
|
+
constructor(options) {
|
|
75
|
+
this.options = options;
|
|
76
|
+
const factory = options.wsFactory ?? globalWebSocketFactory();
|
|
77
|
+
if (!factory)
|
|
78
|
+
throw new Error("events socket: no WebSocket available; pass wsFactory");
|
|
79
|
+
this.factory = factory;
|
|
80
|
+
this.backoff = options.reconnectMinMs ?? DEFAULT_RECONNECT_MIN_MS;
|
|
81
|
+
}
|
|
82
|
+
get state() {
|
|
83
|
+
return this.current;
|
|
84
|
+
}
|
|
85
|
+
/** Bumped each time a socket confirms its subscription. */
|
|
86
|
+
get generation() {
|
|
87
|
+
return this.gen;
|
|
88
|
+
}
|
|
89
|
+
hasPending() {
|
|
90
|
+
return this.frames.length > 0 || this.overflow;
|
|
91
|
+
}
|
|
92
|
+
/** Take every buffered frame, and whether any were dropped, in arrival order. */
|
|
93
|
+
take() {
|
|
94
|
+
const batch = { frames: this.frames, overflowed: this.overflow, generation: this.gen };
|
|
95
|
+
this.frames = [];
|
|
96
|
+
this.bufferedBytes = 0;
|
|
97
|
+
this.overflow = false;
|
|
98
|
+
return batch;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolves on the next buffered frame or the next time a socket goes live. Never rejects; an abort
|
|
102
|
+
* only unregisters the waiter, so a long outage does not pile them up.
|
|
103
|
+
*/
|
|
104
|
+
changed(signal) {
|
|
105
|
+
return new Promise((resolve) => {
|
|
106
|
+
if (signal?.aborted)
|
|
107
|
+
return;
|
|
108
|
+
this.waiters.push(resolve);
|
|
109
|
+
signal?.addEventListener("abort", () => {
|
|
110
|
+
this.waiters = this.waiters.filter((waiter) => waiter !== resolve);
|
|
111
|
+
}, { once: true });
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
start() {
|
|
115
|
+
if (this.current !== "idle" && this.current !== "stopped")
|
|
116
|
+
return;
|
|
117
|
+
this.current = "connecting";
|
|
118
|
+
void this.open();
|
|
119
|
+
}
|
|
120
|
+
stop() {
|
|
121
|
+
this.current = "stopped";
|
|
122
|
+
this.teardown();
|
|
123
|
+
if (this.reconnectTimer)
|
|
124
|
+
clearTimeout(this.reconnectTimer);
|
|
125
|
+
this.reconnectTimer = null;
|
|
126
|
+
this.notify();
|
|
127
|
+
}
|
|
128
|
+
notify() {
|
|
129
|
+
const waiters = this.waiters;
|
|
130
|
+
this.waiters = [];
|
|
131
|
+
for (const resolve of waiters)
|
|
132
|
+
resolve();
|
|
133
|
+
}
|
|
134
|
+
async open() {
|
|
135
|
+
const attempt = ++this.attempt;
|
|
136
|
+
let token;
|
|
137
|
+
if (this.options.auth.kind === "bearer") {
|
|
138
|
+
try {
|
|
139
|
+
token = await this.options.auth.getToken();
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
if (attempt === this.attempt && this.current !== "stopped")
|
|
143
|
+
this.fail(undefined);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (attempt !== this.attempt || this.current === "stopped")
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let ws;
|
|
150
|
+
try {
|
|
151
|
+
ws = this.factory(eventsSocketUrl(this.options, token));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
this.fail(undefined);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.ws = ws;
|
|
158
|
+
this.openedAt = Date.now();
|
|
159
|
+
// The subscription must be confirmed within the answer window, or the socket is presumed dead.
|
|
160
|
+
this.armAnswer();
|
|
161
|
+
ws.onmessage = (event) => this.onMessage(event.data);
|
|
162
|
+
ws.onclose = (event) => this.fail(closeCode(event));
|
|
163
|
+
// Some runtimes fire error without a close; treat it as one.
|
|
164
|
+
ws.onerror = () => this.fail(undefined);
|
|
165
|
+
}
|
|
166
|
+
onMessage(data) {
|
|
167
|
+
this.clearAnswer();
|
|
168
|
+
this.armSilence();
|
|
169
|
+
if (typeof data !== "string")
|
|
170
|
+
return;
|
|
171
|
+
if (data === PONG_FRAME)
|
|
172
|
+
return;
|
|
173
|
+
let value;
|
|
174
|
+
try {
|
|
175
|
+
value = JSON.parse(data);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!value || typeof value !== "object")
|
|
181
|
+
return;
|
|
182
|
+
const frame = value;
|
|
183
|
+
if (frame.type === "channels") {
|
|
184
|
+
this.current = "live";
|
|
185
|
+
this.gen++;
|
|
186
|
+
this.backoff = this.options.reconnectMinMs ?? DEFAULT_RECONNECT_MIN_MS;
|
|
187
|
+
this.notify();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (frame.type !== "events")
|
|
191
|
+
return;
|
|
192
|
+
const parsed = parseEventsFrame(frame);
|
|
193
|
+
if (!parsed) {
|
|
194
|
+
// A frame the client cannot read is a hole in the chain; the follower must catch up.
|
|
195
|
+
this.overflow = true;
|
|
196
|
+
this.notify();
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const bytes = data.length;
|
|
200
|
+
const maxFrames = this.options.maxBufferedFrames ?? DEFAULT_MAX_BUFFERED_FRAMES;
|
|
201
|
+
const maxBytes = this.options.maxBufferedBytes ?? DEFAULT_MAX_BUFFERED_BYTES;
|
|
202
|
+
if (this.frames.length + 1 > maxFrames || this.bufferedBytes + bytes > maxBytes) {
|
|
203
|
+
// Everything buffered is in the backbone already, so dropping it costs one catch-up, never an event.
|
|
204
|
+
this.frames = [];
|
|
205
|
+
this.bufferedBytes = 0;
|
|
206
|
+
this.overflow = true;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
this.frames.push(parsed);
|
|
210
|
+
this.bufferedBytes += bytes;
|
|
211
|
+
}
|
|
212
|
+
this.notify();
|
|
213
|
+
}
|
|
214
|
+
/** The socket closed or failed: tear it down and schedule the next attempt. */
|
|
215
|
+
fail(code) {
|
|
216
|
+
const lived = this.openedAt > 0 ? Date.now() - this.openedAt : 0;
|
|
217
|
+
this.teardown();
|
|
218
|
+
if (this.current === "stopped")
|
|
219
|
+
return;
|
|
220
|
+
this.current = "down";
|
|
221
|
+
const immediate = code !== undefined && REAUTH_CLOSE_CODES.has(code) && lived >= MIN_HEALTHY_LIFETIME_MS;
|
|
222
|
+
const delay = immediate ? 0 : this.backoff;
|
|
223
|
+
if (!immediate)
|
|
224
|
+
this.backoff = Math.min(this.options.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS, this.backoff * 2);
|
|
225
|
+
this.reconnectTimer = setTimeout(() => {
|
|
226
|
+
this.reconnectTimer = null;
|
|
227
|
+
if (this.current === "stopped")
|
|
228
|
+
return;
|
|
229
|
+
this.current = "connecting";
|
|
230
|
+
void this.open();
|
|
231
|
+
}, delay);
|
|
232
|
+
}
|
|
233
|
+
teardown() {
|
|
234
|
+
this.attempt++;
|
|
235
|
+
this.clearAnswer();
|
|
236
|
+
if (this.silenceTimer)
|
|
237
|
+
clearTimeout(this.silenceTimer);
|
|
238
|
+
this.silenceTimer = null;
|
|
239
|
+
this.openedAt = 0;
|
|
240
|
+
const ws = this.ws;
|
|
241
|
+
this.ws = null;
|
|
242
|
+
if (!ws)
|
|
243
|
+
return;
|
|
244
|
+
ws.onopen = null;
|
|
245
|
+
ws.onmessage = null;
|
|
246
|
+
ws.onclose = null;
|
|
247
|
+
ws.onerror = null;
|
|
248
|
+
try {
|
|
249
|
+
ws.close();
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// Already closed.
|
|
253
|
+
}
|
|
254
|
+
const killable = ws;
|
|
255
|
+
if (typeof killable.terminate === "function") {
|
|
256
|
+
try {
|
|
257
|
+
killable.terminate();
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Already destroyed.
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
armSilence() {
|
|
265
|
+
if (this.silenceTimer)
|
|
266
|
+
clearTimeout(this.silenceTimer);
|
|
267
|
+
this.silenceTimer = setTimeout(() => {
|
|
268
|
+
this.silenceTimer = null;
|
|
269
|
+
const ws = this.ws;
|
|
270
|
+
if (!ws)
|
|
271
|
+
return;
|
|
272
|
+
try {
|
|
273
|
+
ws.send(PING_FRAME);
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
this.fail(undefined);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
this.armAnswer();
|
|
280
|
+
}, this.options.pingAfterMs ?? DEFAULT_PING_AFTER_MS);
|
|
281
|
+
}
|
|
282
|
+
armAnswer() {
|
|
283
|
+
this.clearAnswer();
|
|
284
|
+
this.answerTimer = setTimeout(() => {
|
|
285
|
+
this.answerTimer = null;
|
|
286
|
+
this.fail(undefined);
|
|
287
|
+
}, this.options.pongTimeoutMs ?? DEFAULT_PONG_TIMEOUT_MS);
|
|
288
|
+
}
|
|
289
|
+
clearAnswer() {
|
|
290
|
+
if (this.answerTimer)
|
|
291
|
+
clearTimeout(this.answerTimer);
|
|
292
|
+
this.answerTimer = null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=events-socket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-socket.js","sourceRoot":"","sources":["../src/events-socket.ts"],"names":[],"mappings":"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"}
|
package/dist/events.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { CatalystEvent } from "@catalyst-cloud/schema";
|
|
2
|
-
import type { AuthStrategy } from "./live-sync-client.js";
|
|
2
|
+
import type { AuthStrategy, WebSocketFactory } from "./live-sync-client.js";
|
|
3
|
+
import { type EventsSocketOptions } from "./events-socket.js";
|
|
3
4
|
import { type WriterGuardOptions } from "./replica/writer-lock.js";
|
|
4
5
|
export type { CatalystEvent } from "@catalyst-cloud/schema";
|
|
6
|
+
export { EventsChannelClient, eventsSocketUrl, type EventsFrame, type EventsSocketBatch, type EventsSocketOptions, type EventsSocketState, } from "./events-socket.js";
|
|
5
7
|
export interface EventCachePaths {
|
|
6
8
|
directory: string;
|
|
7
9
|
cursor: string;
|
|
@@ -23,6 +25,16 @@ export interface EventSyncOptions {
|
|
|
23
25
|
writerGuard?: WriterGuardOptions;
|
|
24
26
|
now?: () => Date;
|
|
25
27
|
sleep?: (ms: number, signal: AbortSignal) => Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Take events from the tenant's events socket instead of polling (CTC-5295). Default true when the
|
|
30
|
+
* runtime has a global `WebSocket` or `wsFactory` is given. The socket opens on `start()` or
|
|
31
|
+
* `waitForChange()`, never on a bare `syncOnce()`, and closes on `stop()`.
|
|
32
|
+
*/
|
|
33
|
+
push?: boolean;
|
|
34
|
+
/** Opens the events socket. Defaults to the runtime's global `WebSocket`. */
|
|
35
|
+
wsFactory?: WebSocketFactory;
|
|
36
|
+
/** Events socket timing and buffer bounds; the defaults suit a long-running follower. */
|
|
37
|
+
socket?: Pick<EventsSocketOptions, "pingAfterMs" | "pongTimeoutMs" | "reconnectMinMs" | "reconnectMaxMs" | "maxBufferedFrames" | "maxBufferedBytes">;
|
|
26
38
|
}
|
|
27
39
|
export interface EventSyncStatus {
|
|
28
40
|
state: "idle" | "syncing" | "stopped" | "failed";
|
|
@@ -30,6 +42,8 @@ export interface EventSyncStatus {
|
|
|
30
42
|
head: number | null;
|
|
31
43
|
lastSyncAt: string | null;
|
|
32
44
|
error: string | null;
|
|
45
|
+
/** How new events arrive: `push` while the events socket is live, else `poll`. */
|
|
46
|
+
transport?: "push" | "poll";
|
|
33
47
|
}
|
|
34
48
|
export interface EventSyncResult {
|
|
35
49
|
appended: number;
|
|
@@ -55,6 +69,10 @@ export declare class CatalystEventSync {
|
|
|
55
69
|
private running;
|
|
56
70
|
private recoveredCursor;
|
|
57
71
|
private floor;
|
|
72
|
+
private socket;
|
|
73
|
+
/** The socket generation the cache last caught up under; a new one needs a backbone catch-up. */
|
|
74
|
+
private syncedGeneration;
|
|
75
|
+
private catchUpPending;
|
|
58
76
|
private current;
|
|
59
77
|
constructor(options: EventSyncOptions);
|
|
60
78
|
status(): EventSyncStatus;
|
|
@@ -62,6 +80,25 @@ export declare class CatalystEventSync {
|
|
|
62
80
|
start(): Promise<void>;
|
|
63
81
|
stop(): Promise<void>;
|
|
64
82
|
private loop;
|
|
83
|
+
/**
|
|
84
|
+
* Wait up to `maxMs` for something to sync: a pushed frame, or the events socket going live (which
|
|
85
|
+
* needs a catch-up). Opens the events socket on first call when push is on. Resolves true when a
|
|
86
|
+
* change ended the wait, false on timeout; rejects only when `signal` aborts. Without a socket it
|
|
87
|
+
* is a plain sleep, so a caller's own loop can use it either way.
|
|
88
|
+
*/
|
|
89
|
+
waitForChange(maxMs: number, signal: AbortSignal): Promise<boolean>;
|
|
90
|
+
private ensureSocket;
|
|
91
|
+
private closeSocket;
|
|
92
|
+
private needsCatchUp;
|
|
93
|
+
/**
|
|
94
|
+
* The push path. Apply buffered frames that chain from the cursor with no request. Read the backbone
|
|
95
|
+
* from the cursor instead when this socket generation has not caught up yet (subscribe first: the
|
|
96
|
+
* frames buffered meanwhile are deduped by sequence after), when a frame starts past the cursor, is
|
|
97
|
+
* flagged `gap`, or carries an event without its payload, or when the buffer overflowed.
|
|
98
|
+
*/
|
|
99
|
+
private readPushed;
|
|
100
|
+
/** Apply frames that chain from `cursor`; stop at the first one that does not. */
|
|
101
|
+
private applyFrames;
|
|
65
102
|
private request;
|
|
66
103
|
private readCurrentHead;
|
|
67
104
|
private readPage;
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|