@korajs/sync 0.1.0
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/chunk-TU345YUC.js +23 -0
- package/dist/chunk-TU345YUC.js.map +1 -0
- package/dist/index.cjs +1720 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +505 -0
- package/dist/index.d.ts +505 -0
- package/dist/index.js +1659 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.cjs +146 -0
- package/dist/internal.cjs.map +1 -0
- package/dist/internal.d.cts +68 -0
- package/dist/internal.d.ts +68 -0
- package/dist/internal.js +102 -0
- package/dist/internal.js.map +1 -0
- package/dist/transport-B5EFsr5F.d.cts +215 -0
- package/dist/transport-B5EFsr5F.d.ts +215 -0
- package/package.json +56 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { S as SyncMessage, a as SerializedOperation, W as WireFormat, b as SyncTransport, T as TransportOptions, c as TransportMessageHandler, d as TransportCloseHandler, e as TransportErrorHandler, Q as QueueStorage, f as SyncConfig, g as SyncStatusInfo, h as SyncState } from './transport-B5EFsr5F.cjs';
|
|
2
|
+
export { A as AcknowledgmentMessage, E as ErrorMessage, H as HandshakeMessage, i as HandshakeResponseMessage, O as OperationBatchMessage, j as SYNC_STATES, k as SYNC_STATUSES, l as SyncScopeContext, m as SyncStatus, n as isAcknowledgmentMessage, o as isErrorMessage, p as isHandshakeMessage, q as isHandshakeResponseMessage, r as isOperationBatchMessage, s as isSyncMessage } from './transport-B5EFsr5F.cjs';
|
|
3
|
+
import { VersionVector, Operation, KoraEventEmitter, TimeSource, ConnectionQuality } from '@korajs/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Result of applying a remote operation to the store.
|
|
7
|
+
*/
|
|
8
|
+
type ApplyResult = 'applied' | 'duplicate' | 'skipped';
|
|
9
|
+
/**
|
|
10
|
+
* Interface that the local store must implement for sync.
|
|
11
|
+
* This decouples @korajs/sync from @korajs/store — the store satisfies this interface.
|
|
12
|
+
*
|
|
13
|
+
* @korajs/store's Store class already implements these methods:
|
|
14
|
+
* - getVersionVector() — returns the current version vector
|
|
15
|
+
* - getNodeId() — returns this instance's nodeId
|
|
16
|
+
* - applyRemoteOperation(op) — applies a remote op with dedup and merge
|
|
17
|
+
* - getOperationRange(nodeId, fromSeq, toSeq) — fetches operations from the log
|
|
18
|
+
*/
|
|
19
|
+
interface SyncStore {
|
|
20
|
+
/** Get the current version vector for this store */
|
|
21
|
+
getVersionVector(): VersionVector;
|
|
22
|
+
/** Get the node ID for this store instance */
|
|
23
|
+
getNodeId(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Apply a remote operation to the local store.
|
|
26
|
+
* Must handle deduplication (content-addressed) and merge resolution.
|
|
27
|
+
* @returns 'applied' if the operation was new, 'duplicate' if already seen, 'skipped' if filtered
|
|
28
|
+
*/
|
|
29
|
+
applyRemoteOperation(op: Operation): Promise<ApplyResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Get operations from a specific node within a sequence range.
|
|
32
|
+
* Used for computing deltas during sync.
|
|
33
|
+
* @param nodeId - The originating node
|
|
34
|
+
* @param fromSeq - Start sequence number (inclusive)
|
|
35
|
+
* @param toSeq - End sequence number (inclusive)
|
|
36
|
+
*/
|
|
37
|
+
getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type EncodedMessage = string | Uint8Array;
|
|
41
|
+
/**
|
|
42
|
+
* Interface for encoding/decoding sync protocol messages.
|
|
43
|
+
*/
|
|
44
|
+
interface MessageSerializer {
|
|
45
|
+
encode(message: SyncMessage): EncodedMessage;
|
|
46
|
+
decode(data: string | Uint8Array | ArrayBuffer): SyncMessage;
|
|
47
|
+
encodeOperation(op: Operation): SerializedOperation;
|
|
48
|
+
decodeOperation(serialized: SerializedOperation): Operation;
|
|
49
|
+
setWireFormat?(format: WireFormat): void;
|
|
50
|
+
getWireFormat?(): WireFormat;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Convert a VersionVector (Map) to a plain object for wire transmission.
|
|
54
|
+
*/
|
|
55
|
+
declare function versionVectorToWire(vector: VersionVector): Record<string, number>;
|
|
56
|
+
/**
|
|
57
|
+
* Convert a wire-format version vector (plain object) back to a VersionVector (Map).
|
|
58
|
+
*/
|
|
59
|
+
declare function wireToVersionVector(wire: Record<string, number>): VersionVector;
|
|
60
|
+
/**
|
|
61
|
+
* JSON-based message serializer.
|
|
62
|
+
*/
|
|
63
|
+
declare class JsonMessageSerializer implements MessageSerializer {
|
|
64
|
+
encode(message: SyncMessage): string;
|
|
65
|
+
decode(data: string | Uint8Array | ArrayBuffer): SyncMessage;
|
|
66
|
+
encodeOperation(op: Operation): SerializedOperation;
|
|
67
|
+
decodeOperation(serialized: SerializedOperation): Operation;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Protobuf-based serializer for sync messages.
|
|
71
|
+
*/
|
|
72
|
+
declare class ProtobufMessageSerializer implements MessageSerializer {
|
|
73
|
+
encode(message: SyncMessage): Uint8Array;
|
|
74
|
+
decode(data: string | Uint8Array | ArrayBuffer): SyncMessage;
|
|
75
|
+
encodeOperation(op: Operation): SerializedOperation;
|
|
76
|
+
decodeOperation(serialized: SerializedOperation): Operation;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Negotiated serializer that supports runtime wire-format switching.
|
|
80
|
+
*/
|
|
81
|
+
declare class NegotiatedMessageSerializer implements MessageSerializer {
|
|
82
|
+
private readonly json;
|
|
83
|
+
private readonly protobuf;
|
|
84
|
+
private wireFormat;
|
|
85
|
+
constructor(initialWireFormat?: WireFormat);
|
|
86
|
+
encode(message: SyncMessage): EncodedMessage;
|
|
87
|
+
decode(data: string | Uint8Array | ArrayBuffer): SyncMessage;
|
|
88
|
+
encodeOperation(op: Operation): SerializedOperation;
|
|
89
|
+
decodeOperation(serialized: SerializedOperation): Operation;
|
|
90
|
+
setWireFormat(format: WireFormat): void;
|
|
91
|
+
getWireFormat(): WireFormat;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* WebSocket event interface for dependency injection.
|
|
96
|
+
* Matches the subset of the browser WebSocket API that we need.
|
|
97
|
+
*/
|
|
98
|
+
interface WebSocketLike {
|
|
99
|
+
readonly readyState: number;
|
|
100
|
+
send(data: string | Uint8Array): void;
|
|
101
|
+
close(code?: number, reason?: string): void;
|
|
102
|
+
onopen: ((event: unknown) => void) | null;
|
|
103
|
+
onmessage: ((event: {
|
|
104
|
+
data: unknown;
|
|
105
|
+
}) => void) | null;
|
|
106
|
+
onclose: ((event: {
|
|
107
|
+
reason: string;
|
|
108
|
+
code: number;
|
|
109
|
+
}) => void) | null;
|
|
110
|
+
onerror: ((event: unknown) => void) | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Constructor for WebSocket-like objects. Allows injection of mock WebSocket for testing.
|
|
114
|
+
*/
|
|
115
|
+
type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike;
|
|
116
|
+
/**
|
|
117
|
+
* Options for the WebSocket transport.
|
|
118
|
+
*/
|
|
119
|
+
interface WebSocketTransportOptions {
|
|
120
|
+
/** Custom serializer. Defaults to JSON. */
|
|
121
|
+
serializer?: MessageSerializer;
|
|
122
|
+
/** Injectable WebSocket constructor for testing. Defaults to globalThis.WebSocket. */
|
|
123
|
+
WebSocketImpl?: WebSocketConstructor;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* WebSocket-based sync transport implementation.
|
|
127
|
+
*/
|
|
128
|
+
declare class WebSocketTransport implements SyncTransport {
|
|
129
|
+
private ws;
|
|
130
|
+
private messageHandler;
|
|
131
|
+
private closeHandler;
|
|
132
|
+
private errorHandler;
|
|
133
|
+
private readonly serializer;
|
|
134
|
+
private readonly WebSocketImpl;
|
|
135
|
+
constructor(options?: WebSocketTransportOptions);
|
|
136
|
+
connect(url: string, options?: TransportOptions): Promise<void>;
|
|
137
|
+
disconnect(): Promise<void>;
|
|
138
|
+
send(message: SyncMessage): void;
|
|
139
|
+
onMessage(handler: TransportMessageHandler): void;
|
|
140
|
+
onClose(handler: TransportCloseHandler): void;
|
|
141
|
+
onError(handler: TransportErrorHandler): void;
|
|
142
|
+
isConnected(): boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface HttpLongPollingTransportOptions {
|
|
146
|
+
serializer?: MessageSerializer;
|
|
147
|
+
fetchImpl?: typeof fetch;
|
|
148
|
+
retryDelayMs?: number;
|
|
149
|
+
preferWebSocket?: boolean;
|
|
150
|
+
webSocketFactory?: () => SyncTransport;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* HTTP long-polling transport with optional WebSocket upgrade.
|
|
154
|
+
*/
|
|
155
|
+
declare class HttpLongPollingTransport implements SyncTransport {
|
|
156
|
+
private readonly serializer;
|
|
157
|
+
private readonly fetchImpl;
|
|
158
|
+
private readonly retryDelayMs;
|
|
159
|
+
private readonly preferWebSocket;
|
|
160
|
+
private readonly webSocketFactory;
|
|
161
|
+
private messageHandler;
|
|
162
|
+
private closeHandler;
|
|
163
|
+
private errorHandler;
|
|
164
|
+
private connected;
|
|
165
|
+
private polling;
|
|
166
|
+
private url;
|
|
167
|
+
private authToken;
|
|
168
|
+
private pollAbort;
|
|
169
|
+
private upgradedTransport;
|
|
170
|
+
constructor(options?: HttpLongPollingTransportOptions);
|
|
171
|
+
connect(url: string, options?: TransportOptions): Promise<void>;
|
|
172
|
+
disconnect(): Promise<void>;
|
|
173
|
+
send(message: SyncMessage): void;
|
|
174
|
+
onMessage(handler: TransportMessageHandler): void;
|
|
175
|
+
onClose(handler: TransportCloseHandler): void;
|
|
176
|
+
onError(handler: TransportErrorHandler): void;
|
|
177
|
+
isConnected(): boolean;
|
|
178
|
+
private tryUpgradeToWebSocket;
|
|
179
|
+
private postMessage;
|
|
180
|
+
private runPollLoop;
|
|
181
|
+
private makePollHeaders;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Configuration for the chaos transport.
|
|
186
|
+
*/
|
|
187
|
+
interface ChaosConfig {
|
|
188
|
+
/** Probability of dropping a message (0-1). Defaults to 0. */
|
|
189
|
+
dropRate?: number;
|
|
190
|
+
/** Probability of duplicating a message (0-1). Defaults to 0. */
|
|
191
|
+
duplicateRate?: number;
|
|
192
|
+
/** Probability of reordering messages (0-1). Defaults to 0. */
|
|
193
|
+
reorderRate?: number;
|
|
194
|
+
/** Maximum latency in ms for delayed messages. Defaults to 0. */
|
|
195
|
+
maxLatency?: number;
|
|
196
|
+
/** Injectable random source for deterministic testing. Returns value in [0, 1). */
|
|
197
|
+
randomSource?: () => number;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Chaos transport that wraps another transport and injects faults.
|
|
201
|
+
* Used for testing sync convergence under unreliable network conditions.
|
|
202
|
+
*
|
|
203
|
+
* Supports message dropping, duplication, reordering, and latency injection.
|
|
204
|
+
* All random behavior is injectable for deterministic, reproducible tests.
|
|
205
|
+
*/
|
|
206
|
+
declare class ChaosTransport implements SyncTransport {
|
|
207
|
+
private readonly inner;
|
|
208
|
+
private readonly dropRate;
|
|
209
|
+
private readonly duplicateRate;
|
|
210
|
+
private readonly reorderRate;
|
|
211
|
+
private readonly maxLatency;
|
|
212
|
+
private readonly random;
|
|
213
|
+
private messageHandler;
|
|
214
|
+
private reorderBuffer;
|
|
215
|
+
private timers;
|
|
216
|
+
constructor(inner: SyncTransport, config?: ChaosConfig);
|
|
217
|
+
connect(url: string, options?: TransportOptions): Promise<void>;
|
|
218
|
+
disconnect(): Promise<void>;
|
|
219
|
+
send(message: SyncMessage): void;
|
|
220
|
+
onMessage(handler: TransportMessageHandler): void;
|
|
221
|
+
onClose(handler: TransportCloseHandler): void;
|
|
222
|
+
onError(handler: TransportErrorHandler): void;
|
|
223
|
+
isConnected(): boolean;
|
|
224
|
+
private handleIncoming;
|
|
225
|
+
private deliverIncoming;
|
|
226
|
+
private flushReorderBuffer;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* A batch of operations taken from the queue for sending.
|
|
231
|
+
*/
|
|
232
|
+
interface OutboundBatch {
|
|
233
|
+
/** Unique identifier for this batch */
|
|
234
|
+
batchId: string;
|
|
235
|
+
/** Operations in this batch, in causal order */
|
|
236
|
+
operations: Operation[];
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Outbound operation queue with pluggable persistence.
|
|
240
|
+
* Manages operations waiting to be sent to the sync server.
|
|
241
|
+
*
|
|
242
|
+
* Operations are deduplicated by ID (content-addressed) and maintained
|
|
243
|
+
* in causal order via topological sort.
|
|
244
|
+
*/
|
|
245
|
+
declare class OutboundQueue {
|
|
246
|
+
private readonly storage;
|
|
247
|
+
private queue;
|
|
248
|
+
private readonly seen;
|
|
249
|
+
private readonly inFlight;
|
|
250
|
+
private nextBatchId;
|
|
251
|
+
private initialized;
|
|
252
|
+
constructor(storage: QueueStorage);
|
|
253
|
+
/**
|
|
254
|
+
* Load persisted operations from storage.
|
|
255
|
+
* Must be called before using the queue.
|
|
256
|
+
*/
|
|
257
|
+
initialize(): Promise<void>;
|
|
258
|
+
/**
|
|
259
|
+
* Add an operation to the outbound queue.
|
|
260
|
+
* Deduplicates by operation ID. Persists to storage.
|
|
261
|
+
*/
|
|
262
|
+
enqueue(op: Operation): Promise<void>;
|
|
263
|
+
/**
|
|
264
|
+
* Take a batch of operations from the front of the queue.
|
|
265
|
+
* Moves them to in-flight status. Returns null if queue is empty.
|
|
266
|
+
*
|
|
267
|
+
* @param batchSize - Maximum number of operations in the batch
|
|
268
|
+
*/
|
|
269
|
+
takeBatch(batchSize: number): OutboundBatch | null;
|
|
270
|
+
/**
|
|
271
|
+
* Acknowledge a batch, removing its operations permanently.
|
|
272
|
+
*/
|
|
273
|
+
acknowledge(batchId: string): Promise<void>;
|
|
274
|
+
/**
|
|
275
|
+
* Return a failed batch to the front of the queue for retry.
|
|
276
|
+
* Prepends the operations to maintain priority.
|
|
277
|
+
*/
|
|
278
|
+
returnBatch(batchId: string): void;
|
|
279
|
+
/**
|
|
280
|
+
* Number of operations waiting in the queue (not counting in-flight).
|
|
281
|
+
*/
|
|
282
|
+
get size(): number;
|
|
283
|
+
/**
|
|
284
|
+
* Total operations including in-flight.
|
|
285
|
+
*/
|
|
286
|
+
get totalPending(): number;
|
|
287
|
+
/**
|
|
288
|
+
* Whether the queue has any operations to send.
|
|
289
|
+
*/
|
|
290
|
+
get hasOperations(): boolean;
|
|
291
|
+
/**
|
|
292
|
+
* Peek at the first `count` operations without removing them.
|
|
293
|
+
*/
|
|
294
|
+
peek(count: number): Operation[];
|
|
295
|
+
/**
|
|
296
|
+
* Whether initialize() has been called.
|
|
297
|
+
*/
|
|
298
|
+
get isInitialized(): boolean;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Options for creating a SyncEngine.
|
|
303
|
+
*/
|
|
304
|
+
interface SyncEngineOptions {
|
|
305
|
+
/** Transport implementation (WebSocket, memory, etc.) */
|
|
306
|
+
transport: SyncTransport;
|
|
307
|
+
/** Local store implementing SyncStore */
|
|
308
|
+
store: SyncStore;
|
|
309
|
+
/** Sync configuration */
|
|
310
|
+
config: SyncConfig;
|
|
311
|
+
/** Message serializer. Defaults to JSON. */
|
|
312
|
+
serializer?: MessageSerializer;
|
|
313
|
+
/** Event emitter for DevTools integration */
|
|
314
|
+
emitter?: KoraEventEmitter;
|
|
315
|
+
/** Queue storage for persistent outbound queue. Defaults to in-memory. */
|
|
316
|
+
queueStorage?: QueueStorage;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Core sync orchestrator. Manages the sync lifecycle:
|
|
320
|
+
* disconnected → connecting → handshaking → syncing → streaming
|
|
321
|
+
*
|
|
322
|
+
* Coordinates handshake, delta exchange, and real-time streaming
|
|
323
|
+
* between a local store and a remote sync server.
|
|
324
|
+
*/
|
|
325
|
+
declare class SyncEngine {
|
|
326
|
+
private state;
|
|
327
|
+
private readonly transport;
|
|
328
|
+
private readonly store;
|
|
329
|
+
private readonly config;
|
|
330
|
+
private readonly serializer;
|
|
331
|
+
private readonly emitter;
|
|
332
|
+
private readonly outboundQueue;
|
|
333
|
+
private readonly batchSize;
|
|
334
|
+
private remoteVector;
|
|
335
|
+
private lastSyncedAt;
|
|
336
|
+
private currentBatch;
|
|
337
|
+
private deltaBatchesReceived;
|
|
338
|
+
private deltaReceiveComplete;
|
|
339
|
+
private deltaSendComplete;
|
|
340
|
+
constructor(options: SyncEngineOptions);
|
|
341
|
+
/**
|
|
342
|
+
* Start the sync engine: connect → handshake → delta exchange → streaming.
|
|
343
|
+
*/
|
|
344
|
+
start(): Promise<void>;
|
|
345
|
+
/**
|
|
346
|
+
* Stop the sync engine. Disconnects the transport.
|
|
347
|
+
*/
|
|
348
|
+
stop(): Promise<void>;
|
|
349
|
+
private ensureDisconnected;
|
|
350
|
+
/**
|
|
351
|
+
* Push a local operation to the outbound queue.
|
|
352
|
+
* If streaming, flushes immediately.
|
|
353
|
+
*/
|
|
354
|
+
pushOperation(op: Operation): Promise<void>;
|
|
355
|
+
/**
|
|
356
|
+
* Get the current developer-facing sync status.
|
|
357
|
+
*/
|
|
358
|
+
getStatus(): SyncStatusInfo;
|
|
359
|
+
/**
|
|
360
|
+
* Get the current internal state (for testing).
|
|
361
|
+
*/
|
|
362
|
+
getState(): SyncState;
|
|
363
|
+
/**
|
|
364
|
+
* Get the outbound queue (for testing).
|
|
365
|
+
*/
|
|
366
|
+
getOutboundQueue(): OutboundQueue;
|
|
367
|
+
private handleMessage;
|
|
368
|
+
private handleHandshakeResponse;
|
|
369
|
+
private sendDelta;
|
|
370
|
+
private collectDelta;
|
|
371
|
+
private handleOperationBatch;
|
|
372
|
+
private handleAcknowledgment;
|
|
373
|
+
private handleError;
|
|
374
|
+
private checkDeltaComplete;
|
|
375
|
+
private flushQueue;
|
|
376
|
+
private handleTransportClose;
|
|
377
|
+
private handleTransportError;
|
|
378
|
+
private transitionTo;
|
|
379
|
+
private setSerializerWireFormat;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Configuration for the connection monitor.
|
|
384
|
+
*/
|
|
385
|
+
interface ConnectionMonitorConfig {
|
|
386
|
+
/** Number of latency samples to keep in the rolling window. Defaults to 20. */
|
|
387
|
+
windowSize?: number;
|
|
388
|
+
/** Time in ms after which the connection is considered stale. Defaults to 30000. */
|
|
389
|
+
staleThreshold?: number;
|
|
390
|
+
/** Injectable time source for deterministic testing */
|
|
391
|
+
timeSource?: TimeSource;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Monitors connection quality based on RTT latency samples,
|
|
395
|
+
* missed acknowledgments, and activity timestamps.
|
|
396
|
+
*/
|
|
397
|
+
declare class ConnectionMonitor {
|
|
398
|
+
private readonly windowSize;
|
|
399
|
+
private readonly staleThreshold;
|
|
400
|
+
private readonly timeSource;
|
|
401
|
+
private latencies;
|
|
402
|
+
private missedAcks;
|
|
403
|
+
private lastActivityTime;
|
|
404
|
+
constructor(config?: ConnectionMonitorConfig);
|
|
405
|
+
/**
|
|
406
|
+
* Record a round-trip time sample.
|
|
407
|
+
*/
|
|
408
|
+
recordLatency(ms: number): void;
|
|
409
|
+
/**
|
|
410
|
+
* Record a missed acknowledgment (message sent but no response received).
|
|
411
|
+
*/
|
|
412
|
+
recordMissedAck(): void;
|
|
413
|
+
/**
|
|
414
|
+
* Record any activity (message sent or received).
|
|
415
|
+
*/
|
|
416
|
+
recordActivity(): void;
|
|
417
|
+
/**
|
|
418
|
+
* Assess current connection quality based on collected metrics.
|
|
419
|
+
*
|
|
420
|
+
* Quality thresholds (average RTT):
|
|
421
|
+
* - excellent: < 100ms, 0 missed acks
|
|
422
|
+
* - good: < 300ms, ≤ 1 missed ack
|
|
423
|
+
* - fair: < 1000ms, ≤ 3 missed acks
|
|
424
|
+
* - poor: < 5000ms or > 3 missed acks
|
|
425
|
+
* - offline: no activity for staleThreshold ms
|
|
426
|
+
*/
|
|
427
|
+
getQuality(): ConnectionQuality;
|
|
428
|
+
/**
|
|
429
|
+
* Reset all metrics. Call on disconnect.
|
|
430
|
+
*/
|
|
431
|
+
reset(): void;
|
|
432
|
+
/**
|
|
433
|
+
* Get the current average latency in ms. Returns null if no samples.
|
|
434
|
+
*/
|
|
435
|
+
getAverageLatency(): number | null;
|
|
436
|
+
/**
|
|
437
|
+
* Get the number of missed acks.
|
|
438
|
+
*/
|
|
439
|
+
getMissedAcks(): number;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Configuration for the reconnection manager.
|
|
444
|
+
*/
|
|
445
|
+
interface ReconnectionConfig {
|
|
446
|
+
/** Initial delay in ms before first reconnection attempt. Defaults to 1000. */
|
|
447
|
+
initialDelay?: number;
|
|
448
|
+
/** Maximum delay in ms between attempts. Defaults to 30000. */
|
|
449
|
+
maxDelay?: number;
|
|
450
|
+
/** Multiplier for exponential backoff. Defaults to 2. */
|
|
451
|
+
multiplier?: number;
|
|
452
|
+
/** Maximum number of reconnection attempts. 0 means unlimited. Defaults to 0. */
|
|
453
|
+
maxAttempts?: number;
|
|
454
|
+
/** Jitter factor (0-1). Random variation applied to delay. Defaults to 0.25. */
|
|
455
|
+
jitter?: number;
|
|
456
|
+
/** Injectable time source for deterministic testing. */
|
|
457
|
+
timeSource?: TimeSource;
|
|
458
|
+
/** Injectable random source for deterministic jitter. Returns value in [0, 1). */
|
|
459
|
+
randomSource?: () => number;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Manages reconnection attempts with exponential backoff and jitter.
|
|
463
|
+
*
|
|
464
|
+
* Formula: min(initialDelay * multiplier^attempt, maxDelay) * (1 + jitter * (random - 0.5) * 2)
|
|
465
|
+
*/
|
|
466
|
+
declare class ReconnectionManager {
|
|
467
|
+
private readonly initialDelay;
|
|
468
|
+
private readonly maxDelay;
|
|
469
|
+
private readonly multiplier;
|
|
470
|
+
private readonly maxAttempts;
|
|
471
|
+
private readonly jitter;
|
|
472
|
+
private readonly random;
|
|
473
|
+
private attempt;
|
|
474
|
+
private timer;
|
|
475
|
+
private stopped;
|
|
476
|
+
private waitResolve;
|
|
477
|
+
constructor(config?: ReconnectionConfig);
|
|
478
|
+
/**
|
|
479
|
+
* Start reconnection attempts. Calls `onReconnect` with exponential backoff.
|
|
480
|
+
*
|
|
481
|
+
* @param onReconnect - Called on each attempt. Return `true` if reconnection succeeded.
|
|
482
|
+
* @returns Promise that resolves when reconnection succeeds or maxAttempts reached.
|
|
483
|
+
*/
|
|
484
|
+
start(onReconnect: () => Promise<boolean>): Promise<boolean>;
|
|
485
|
+
/**
|
|
486
|
+
* Stop any pending reconnection attempt.
|
|
487
|
+
*/
|
|
488
|
+
stop(): void;
|
|
489
|
+
/**
|
|
490
|
+
* Reset the attempt counter. Call after a successful manual reconnection.
|
|
491
|
+
*/
|
|
492
|
+
reset(): void;
|
|
493
|
+
/**
|
|
494
|
+
* Compute the next delay for the current attempt.
|
|
495
|
+
* Exposed for testing purposes.
|
|
496
|
+
*/
|
|
497
|
+
getNextDelay(): number;
|
|
498
|
+
/**
|
|
499
|
+
* Current attempt number (for testing).
|
|
500
|
+
*/
|
|
501
|
+
getAttemptCount(): number;
|
|
502
|
+
private wait;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export { type ApplyResult, type ChaosConfig, ChaosTransport, ConnectionMonitor, type ConnectionMonitorConfig, HttpLongPollingTransport, type HttpLongPollingTransportOptions, JsonMessageSerializer, type MessageSerializer, NegotiatedMessageSerializer, type OutboundBatch, OutboundQueue, ProtobufMessageSerializer, QueueStorage, type ReconnectionConfig, ReconnectionManager, SerializedOperation, SyncConfig, SyncEngine, type SyncEngineOptions, SyncMessage, SyncState, SyncStatusInfo, type SyncStore, SyncTransport, TransportCloseHandler, TransportErrorHandler, TransportMessageHandler, TransportOptions, type WebSocketConstructor, type WebSocketLike, WebSocketTransport, type WebSocketTransportOptions, WireFormat, versionVectorToWire, wireToVersionVector };
|