@topgunbuild/server 0.2.0 → 0.3.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/index.d.ts CHANGED
@@ -1,333 +1,3051 @@
1
- import { LWWRecord, ORMapRecord, Principal, PermissionPolicy, LWWMap, ORMap, PermissionType } from '@topgunbuild/core';
1
+ import { Timestamp, LWWRecord, ORMapRecord, Principal, PermissionPolicy, ConsistencyLevel, ReplicationConfig, LWWMap, ORMap, PermissionType, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, ReplicationLag, ReplicationHealth, ReplicationResult } from '@topgunbuild/core';
2
2
  import { WebSocket } from 'ws';
3
3
  import { PoolConfig, Pool } from 'pg';
4
4
  import pino from 'pino';
5
+ import { EventEmitter } from 'events';
5
6
 
6
- type ORMapValue<V> = {
7
- type: 'OR';
8
- records: ORMapRecord<V>[];
9
- };
10
- type ORMapTombstones = {
11
- type: 'OR_TOMBSTONES';
12
- tags: string[];
13
- };
14
- type StorageValue<V> = LWWRecord<V> | ORMapValue<V> | ORMapTombstones;
15
7
  /**
16
- * Server Persistence Interface (MapStore).
17
- * Aligned with specifications/06_SERVER_INTEGRATIONS.md
8
+ * TaskletScheduler Cooperative multitasking for long-running operations.
18
9
  *
19
- * Note: We include mapName in all methods because a single storage adapter
20
- * instance typically handles multiple maps in the system (e.g. single DB connection).
10
+ * Inspired by Hazelcast's Tasklet pattern, this scheduler allows long operations
11
+ * to yield control back to the event loop periodically, preventing event loop
12
+ * blocking and maintaining responsiveness.
13
+ *
14
+ * Key concepts:
15
+ * - Tasklet: A unit of work that can be paused and resumed
16
+ * - Time budget: Maximum time a tasklet can run before yielding
17
+ * - Cooperative scheduling: Tasklets voluntarily yield when time budget is exhausted
21
18
  */
22
- interface IServerStorage {
19
+ /**
20
+ * Progress state returned by a tasklet after each execution step.
21
+ */
22
+ type ProgressState = 'DONE' | 'MADE_PROGRESS' | 'NO_PROGRESS';
23
+ /**
24
+ * Interface for a tasklet that can be scheduled.
25
+ */
26
+ interface Tasklet<T = void> {
27
+ /** Unique name for logging/metrics */
28
+ readonly name: string;
23
29
  /**
24
- * Initialize the storage connection.
30
+ * Execute one chunk of work.
31
+ * Should check time budget and return appropriate state.
25
32
  */
26
- initialize(): Promise<void>;
33
+ call(): ProgressState;
27
34
  /**
28
- * Close the storage connection.
35
+ * Get the result after tasklet is DONE.
36
+ * Only valid when call() returns 'DONE'.
29
37
  */
30
- close(): Promise<void>;
38
+ getResult(): T;
31
39
  /**
32
- * Loads the value of a given key.
33
- * Called when a client requests a key that is not in the Server RAM (if using partial loading),
34
- * or during sync.
40
+ * Called when tasklet is cancelled before completion.
35
41
  */
36
- load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
42
+ onCancel?(): void;
43
+ }
44
+ /**
45
+ * Configuration for TaskletScheduler.
46
+ */
47
+ interface TaskletSchedulerConfig {
48
+ /** Default time budget per tasklet execution in ms (default: 5) */
49
+ defaultTimeBudgetMs?: number;
50
+ /** Maximum concurrent tasklets (default: 10) */
51
+ maxConcurrent?: number;
52
+ /** Interval between scheduler ticks in ms (default: 1) */
53
+ tickIntervalMs?: number;
54
+ /** Enable metrics collection (default: true) */
55
+ metricsEnabled?: boolean;
56
+ }
57
+ /**
58
+ * Metrics for monitoring scheduler performance.
59
+ */
60
+ interface TaskletSchedulerStats {
61
+ /** Total tasklets scheduled */
62
+ totalScheduled: number;
63
+ /** Tasklets currently running */
64
+ activeTasklets: number;
65
+ /** Tasklets completed successfully */
66
+ completedTasklets: number;
67
+ /** Tasklets cancelled */
68
+ cancelledTasklets: number;
69
+ /** Total iterations across all tasklets */
70
+ totalIterations: number;
71
+ /** Average iterations per tasklet */
72
+ avgIterationsPerTasklet: number;
73
+ /** Tasklets that completed in a single iteration */
74
+ singleIterationCompletions: number;
75
+ /** Time spent in tasklet execution (ms) */
76
+ totalExecutionTimeMs: number;
77
+ }
78
+ /**
79
+ * TaskletScheduler manages cooperative multitasking for long-running operations.
80
+ *
81
+ * Usage:
82
+ * ```typescript
83
+ * const scheduler = new TaskletScheduler();
84
+ *
85
+ * // Schedule a tasklet
86
+ * const result = await scheduler.schedule(new QueryExecutionTasklet(records, query));
87
+ *
88
+ * // Cancel all running tasklets
89
+ * scheduler.cancelAll();
90
+ *
91
+ * // Shutdown scheduler
92
+ * scheduler.shutdown();
93
+ * ```
94
+ */
95
+ declare class TaskletScheduler {
96
+ private readonly config;
97
+ private readonly activeTasklets;
98
+ private tickTimer;
99
+ private isRunning;
100
+ private isShuttingDown;
101
+ private totalScheduled;
102
+ private completedTasklets;
103
+ private cancelledTasklets;
104
+ private totalIterations;
105
+ private singleIterationCompletions;
106
+ private totalExecutionTimeMs;
107
+ constructor(config?: TaskletSchedulerConfig);
37
108
  /**
38
- * Loads multiple keys.
39
- * Optimization for batch requests.
109
+ * Schedule a tasklet for execution.
110
+ * Returns a promise that resolves when the tasklet completes.
40
111
  */
41
- loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
112
+ schedule<T>(tasklet: Tasklet<T>): Promise<T>;
42
113
  /**
43
- * Loads all keys from the store for a specific map.
44
- * Used for pre-loading the cache on startup or understanding dataset size.
114
+ * Run a tasklet synchronously (blocking).
115
+ * Useful for small operations or when cooperative scheduling isn't needed.
45
116
  */
46
- loadAllKeys(mapName: string): Promise<string[]>;
117
+ runSync<T>(tasklet: Tasklet<T>): T;
47
118
  /**
48
- * Stores the key-value pair.
119
+ * Cancel a specific tasklet by name pattern.
120
+ * Returns the number of tasklets cancelled.
49
121
  */
50
- store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
122
+ cancel(namePattern: string | RegExp): number;
51
123
  /**
52
- * Stores multiple entries.
53
- * Used for efficient batch writes to the DB.
124
+ * Cancel all running tasklets.
54
125
  */
55
- storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
126
+ cancelAll(): number;
56
127
  /**
57
- * Deletes the entry with the given key.
128
+ * Get scheduler statistics.
58
129
  */
59
- delete(mapName: string, key: string): Promise<void>;
130
+ getStats(): TaskletSchedulerStats;
60
131
  /**
61
- * Deletes multiple entries.
132
+ * Reset statistics.
62
133
  */
63
- deleteAll(mapName: string, keys: string[]): Promise<void>;
134
+ resetStats(): void;
135
+ /**
136
+ * Shutdown the scheduler.
137
+ * Cancels all running tasklets and stops the tick timer.
138
+ */
139
+ shutdown(): void;
140
+ /**
141
+ * Check if scheduler is running.
142
+ */
143
+ get running(): boolean;
144
+ /**
145
+ * Get number of active tasklets.
146
+ */
147
+ get activeCount(): number;
148
+ private startScheduler;
149
+ private stopScheduler;
150
+ private scheduleTick;
151
+ private tick;
152
+ private completeTasklet;
153
+ private failTasklet;
154
+ private cancelTasklet;
64
155
  }
65
156
 
66
- interface ServerOp {
67
- mapName: string;
68
- key: string;
69
- opType: 'PUT' | 'REMOVE' | 'OR_ADD' | 'OR_REMOVE';
70
- record?: LWWRecord<any>;
71
- orRecord?: ORMapRecord<any>;
72
- orTag?: string;
73
- id?: string;
157
+ /**
158
+ * IteratorTasklet — Base class for tasklets that iterate over collections.
159
+ *
160
+ * Provides cooperative iteration with time-budgeted chunks.
161
+ * Subclasses implement processItem() to handle each item.
162
+ */
163
+
164
+ /**
165
+ * Configuration for iterator tasklets.
166
+ */
167
+ interface IteratorTaskletConfig {
168
+ /** Time budget per iteration in ms (default: 5) */
169
+ timeBudgetMs?: number;
170
+ /** Maximum items to process per iteration (default: 1000) */
171
+ maxItemsPerIteration?: number;
74
172
  }
75
- interface ConnectionContext {
76
- clientId: string;
77
- socket?: WebSocket;
78
- principal?: Principal;
79
- isAuthenticated: boolean;
173
+ /**
174
+ * Abstract base class for iterator-based tasklets.
175
+ *
176
+ * Usage:
177
+ * ```typescript
178
+ * class MyTasklet extends IteratorTasklet<[string, Record], Record[]> {
179
+ * constructor(map: Map<string, Record>) {
180
+ * super('my-tasklet', map.entries());
181
+ * }
182
+ *
183
+ * protected processItem([key, record]: [string, Record]): void {
184
+ * if (matchesCriteria(record)) {
185
+ * this.results.push(record);
186
+ * }
187
+ * }
188
+ *
189
+ * getResult(): Record[] {
190
+ * return this.results;
191
+ * }
192
+ * }
193
+ * ```
194
+ */
195
+ declare abstract class IteratorTasklet<TItem, TResult> implements Tasklet<TResult> {
196
+ abstract readonly name: string;
197
+ protected readonly config: Required<IteratorTaskletConfig>;
198
+ protected readonly iterator: Iterator<TItem>;
199
+ protected itemsProcessed: number;
200
+ protected isDone: boolean;
201
+ constructor(iterator: Iterator<TItem>, config?: IteratorTaskletConfig);
202
+ /**
203
+ * Process a single item from the iterator.
204
+ * Override this in subclasses.
205
+ */
206
+ protected abstract processItem(item: TItem): void;
207
+ /**
208
+ * Get the final result after iteration completes.
209
+ */
210
+ abstract getResult(): TResult;
211
+ /**
212
+ * Execute one chunk of iteration.
213
+ */
214
+ call(): ProgressState;
215
+ /**
216
+ * Called when tasklet is cancelled.
217
+ */
218
+ onCancel(): void;
219
+ /**
220
+ * Get number of items processed so far.
221
+ */
222
+ get processed(): number;
80
223
  }
81
- interface OpContext extends ConnectionContext {
82
- fromCluster: boolean;
83
- originalSenderId?: string;
224
+ /**
225
+ * Simple iterator tasklet that collects items matching a predicate.
226
+ */
227
+ declare class FilterTasklet<T> extends IteratorTasklet<T, T[]> {
228
+ readonly name: string;
229
+ protected readonly results: T[];
230
+ private readonly predicate;
231
+ constructor(name: string, iterator: Iterator<T>, predicate: (item: T) => boolean, config?: IteratorTaskletConfig);
232
+ protected processItem(item: T): void;
233
+ getResult(): T[];
84
234
  }
85
- interface IInterceptor {
235
+ /**
236
+ * Iterator tasklet that transforms items.
237
+ */
238
+ declare class MapTasklet<TIn, TOut> extends IteratorTasklet<TIn, TOut[]> {
239
+ readonly name: string;
240
+ protected readonly results: TOut[];
241
+ private readonly mapper;
242
+ constructor(name: string, iterator: Iterator<TIn>, mapper: (item: TIn) => TOut, config?: IteratorTaskletConfig);
243
+ protected processItem(item: TIn): void;
244
+ getResult(): TOut[];
245
+ }
246
+ /**
247
+ * Iterator tasklet that applies a function to each item (side effects).
248
+ */
249
+ declare class ForEachTasklet<T> extends IteratorTasklet<T, number> {
250
+ readonly name: string;
251
+ private readonly action;
252
+ constructor(name: string, iterator: Iterator<T>, action: (item: T) => void, config?: IteratorTaskletConfig);
253
+ protected processItem(item: T): void;
254
+ getResult(): number;
255
+ }
256
+ /**
257
+ * Iterator tasklet that reduces items to a single value.
258
+ */
259
+ declare class ReduceTasklet<T, TAccum> extends IteratorTasklet<T, TAccum> {
260
+ readonly name: string;
261
+ private accumulator;
262
+ private readonly reducer;
263
+ constructor(name: string, iterator: Iterator<T>, initialValue: TAccum, reducer: (acc: TAccum, item: T) => TAccum, config?: IteratorTaskletConfig);
264
+ protected processItem(item: T): void;
265
+ getResult(): TAccum;
266
+ }
267
+
268
+ /**
269
+ * BufferPool - High-performance buffer reuse for serialization operations.
270
+ * Phase 2.03: Memory Pooling
271
+ *
272
+ * Reduces GC pressure by reusing pre-allocated Uint8Array buffers instead of
273
+ * creating new ones for each serialization operation.
274
+ *
275
+ * Reference: Hazelcast MemoryAllocator pattern
276
+ */
277
+ interface BufferPoolConfig {
86
278
  /**
87
- * Name of the interceptor for logging and debugging.
279
+ * Size of each buffer chunk in bytes.
280
+ * Larger chunks = fewer allocations, but more memory waste.
281
+ * Default: 64KB (65536)
88
282
  */
89
- name: string;
283
+ chunkSize?: number;
90
284
  /**
91
- * Called when a new client connects.
92
- * Throwing an error here will reject the connection.
285
+ * Initial number of buffers to pre-allocate.
286
+ * Default: 16
93
287
  */
94
- onConnection?(context: ConnectionContext): Promise<void>;
288
+ initialSize?: number;
95
289
  /**
96
- * Called when a client disconnects.
290
+ * Maximum buffers to keep in pool.
291
+ * Excess buffers are released to GC.
292
+ * Default: 256
97
293
  */
98
- onDisconnect?(context: ConnectionContext): Promise<void>;
294
+ maxSize?: number;
99
295
  /**
100
- * Called before an operation is applied to the local map/storage.
101
- * Return the (possibly modified) op.
102
- * Return null to silently drop the operation (no error sent to client, no persistence).
103
- * Throwing an error will reject the operation and notify the client.
296
+ * Auto-shrink pool when idle buffers exceed this ratio.
297
+ * Default: true
104
298
  */
105
- onBeforeOp?(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
299
+ autoShrink?: boolean;
106
300
  /**
107
- * Called after an operation has been successfully applied and stored.
301
+ * Shrink threshold - shrink if (available / maxSize) > threshold.
302
+ * Default: 0.75 (75% idle)
108
303
  */
109
- onAfterOp?(op: ServerOp, context: OpContext): Promise<void>;
304
+ shrinkThreshold?: number;
305
+ /**
306
+ * Enable metrics collection.
307
+ * Default: true
308
+ */
309
+ metricsEnabled?: boolean;
110
310
  }
111
-
112
- interface TLSConfig {
311
+ interface BufferPoolStats {
312
+ /** Buffers currently available in pool */
313
+ available: number;
314
+ /** Buffers currently in use */
315
+ inUse: number;
316
+ /** Total buffers ever created */
317
+ created: number;
318
+ /** Total times a buffer was reused */
319
+ reused: number;
320
+ /** Reuse ratio: reused / (created + reused) */
321
+ reuseRatio: number;
322
+ /** Total bytes in pool (available buffers only) */
323
+ poolSizeBytes: number;
324
+ /** Peak concurrent usage */
325
+ peakUsage: number;
326
+ /** Times pool was exhausted (had to create new buffer) */
327
+ misses: number;
328
+ /** Chunk size configuration */
329
+ chunkSize: number;
330
+ /** Max pool size configuration */
331
+ maxSize: number;
332
+ }
333
+ /**
334
+ * High-performance buffer pool for serialization operations.
335
+ *
336
+ * Usage:
337
+ * ```typescript
338
+ * const pool = new BufferPool({ chunkSize: 64 * 1024 });
339
+ * const buffer = pool.acquire();
340
+ * // ... use buffer for serialization ...
341
+ * pool.release(buffer);
342
+ * ```
343
+ *
344
+ * Thread Safety:
345
+ * This pool is designed for single-threaded use (Node.js main thread).
346
+ * For worker threads, create separate pools or copy buffers.
347
+ */
348
+ declare class BufferPool {
349
+ private readonly pool;
350
+ private readonly chunkSize;
351
+ private readonly maxSize;
352
+ private readonly autoShrink;
353
+ private readonly shrinkThreshold;
354
+ private readonly metricsEnabled;
355
+ private inUseCount;
356
+ private createdCount;
357
+ private reusedCount;
358
+ private peakUsage;
359
+ private missCount;
360
+ private readonly pooledBuffers;
361
+ private readonly releasedBuffers;
362
+ constructor(config?: BufferPoolConfig);
113
363
  /**
114
- * Enable TLS for client-facing server (HTTPS + WSS)
115
- * @default false
364
+ * Acquire a buffer from the pool.
365
+ * Creates new buffer if pool is empty.
366
+ *
367
+ * @returns A Uint8Array of exactly chunkSize bytes
116
368
  */
117
- enabled: boolean;
369
+ acquire(): Uint8Array;
118
370
  /**
119
- * Path to certificate file (PEM format)
120
- * Supports chain certificates
371
+ * Release a buffer back to the pool.
372
+ * Buffer contents are cleared before returning to pool.
373
+ *
374
+ * @param buffer - The buffer to release
121
375
  */
122
- certPath: string;
376
+ release(buffer: Uint8Array): void;
123
377
  /**
124
- * Path to private key file (PEM format)
378
+ * Acquire a buffer of specific minimum size.
379
+ * May return a buffer larger than requested.
380
+ * For sizes > chunkSize, creates new buffer (not pooled).
381
+ *
382
+ * @param minSize - Minimum required size in bytes
383
+ * @returns A Uint8Array of at least minSize bytes
125
384
  */
126
- keyPath: string;
385
+ acquireSize(minSize: number): Uint8Array;
127
386
  /**
128
- * Path to CA certificate for verifying client certificates
129
- * Required for mTLS
130
- * @optional
387
+ * Get current pool statistics.
131
388
  */
132
- caCertPath?: string;
389
+ getStats(): BufferPoolStats;
133
390
  /**
134
- * Minimum TLS version
135
- * @default 'TLSv1.2'
391
+ * Clear all buffers from pool.
392
+ * Use for shutdown or memory pressure situations.
136
393
  */
137
- minVersion?: 'TLSv1.2' | 'TLSv1.3';
394
+ clear(): void;
138
395
  /**
139
- * List of allowed cipher suites
140
- * @optional - use Node.js defaults if not specified
396
+ * Manually trigger shrink operation.
397
+ * Removes excess idle buffers to reduce memory footprint.
141
398
  */
142
- ciphers?: string;
399
+ shrink(): void;
143
400
  /**
144
- * Passphrase for encrypted private key
145
- * @optional
401
+ * Pre-warm pool by creating buffers up to specified count.
402
+ * Called automatically in constructor.
403
+ *
404
+ * @param count - Number of buffers to create
146
405
  */
147
- passphrase?: string;
148
- }
149
- interface ClusterTLSConfig extends TLSConfig {
406
+ prewarm(count?: number): void;
150
407
  /**
151
- * Require client certificate (mTLS)
152
- * @default false
408
+ * Reset all metrics to zero.
409
+ * Useful for testing or periodic metric collection.
153
410
  */
154
- requireClientCert?: boolean;
411
+ resetStats(): void;
155
412
  /**
156
- * Verify peer certificates
157
- * Can be disabled in development for self-signed certs
158
- * @default true
413
+ * Get configuration values.
159
414
  */
160
- rejectUnauthorized?: boolean;
415
+ getConfig(): Readonly<Required<BufferPoolConfig>>;
416
+ private createBuffer;
417
+ private shouldShrink;
161
418
  }
419
+ /**
420
+ * Get or create the global buffer pool.
421
+ * Uses default configuration (64KB chunks, 256 max).
422
+ */
423
+ declare function getGlobalBufferPool(): BufferPool;
424
+ /**
425
+ * Replace the global buffer pool with a custom instance.
426
+ * Useful for testing or custom configurations.
427
+ *
428
+ * @param pool - New pool instance, or null to reset to default
429
+ */
430
+ declare function setGlobalBufferPool(pool: BufferPool | null): void;
162
431
 
163
- interface ServerCoordinatorConfig {
164
- port: number;
165
- nodeId: string;
166
- storage?: IServerStorage;
167
- jwtSecret?: string;
168
- host?: string;
169
- clusterPort?: number;
170
- peers?: string[];
171
- securityPolicies?: PermissionPolicy[];
172
- /** Callback to resolve dynamic peer addresses after ports are known */
173
- resolvePeers?: () => string[];
174
- interceptors?: IInterceptor[];
175
- metricsPort?: number;
176
- discovery?: 'manual' | 'kubernetes';
177
- serviceName?: string;
178
- discoveryInterval?: number;
179
- tls?: TLSConfig;
180
- clusterTls?: ClusterTLSConfig;
181
- }
182
- declare class ServerCoordinator {
183
- private httpServer;
184
- private metricsServer?;
185
- private metricsService;
186
- private wss;
187
- private clients;
188
- private interceptors;
189
- private maps;
190
- private hlc;
191
- private storage?;
192
- private jwtSecret;
193
- private queryRegistry;
194
- private cluster;
195
- private partitionService;
196
- private lockManager;
197
- private topicManager;
198
- private securityManager;
199
- private systemManager;
200
- private pendingClusterQueries;
201
- private gcInterval?;
202
- private heartbeatCheckInterval?;
203
- private gcReports;
204
- private mapLoadingPromises;
205
- private _actualPort;
206
- private _actualClusterPort;
207
- private _readyPromise;
208
- private _readyResolve;
209
- constructor(config: ServerCoordinatorConfig);
210
- /** Wait for server to be fully ready (ports assigned) */
211
- ready(): Promise<void>;
212
- /** Get the actual port the server is listening on */
213
- get port(): number;
214
- /** Get the actual cluster port */
215
- get clusterPort(): number;
216
- shutdown(): Promise<void>;
217
- private handleConnection;
218
- private handleMessage;
219
- private updateClientHlc;
220
- private broadcast;
221
- private setupClusterListeners;
222
- private executeLocalQuery;
223
- private finalizeClusterQuery;
224
- private handleLockGranted;
225
- private processLocalOp;
226
- private handleClusterEvent;
227
- getMap(name: string, typeHint?: 'LWW' | 'OR'): LWWMap<string, any> | ORMap<string, any>;
432
+ /**
433
+ * ObjectPool - Generic object pooling for reducing GC pressure.
434
+ * Phase 2.04: Object Pool Implementation
435
+ *
436
+ * Reuses objects instead of creating new ones in hot paths.
437
+ * Works with any plain data structure type.
438
+ */
439
+ interface ObjectPoolConfig<T> {
228
440
  /**
229
- * Returns map after ensuring it's fully loaded from storage.
230
- * Use this for queries to avoid returning empty results during initial load.
441
+ * Factory function to create new objects.
442
+ * Called when pool is empty.
231
443
  */
232
- getMapAsync(name: string, typeHint?: 'LWW' | 'OR'): Promise<LWWMap<string, any> | ORMap<string, any>>;
233
- private loadMapFromStorage;
234
- private startGarbageCollection;
444
+ factory: () => T;
235
445
  /**
236
- * Starts the periodic check for dead clients (those that haven't sent PING).
446
+ * Reset function to clean object before reuse.
447
+ * Should clear all fields to initial state.
237
448
  */
238
- private startHeartbeatCheck;
449
+ reset: (obj: T) => void;
239
450
  /**
240
- * Handles incoming PING message from client.
241
- * Responds with PONG immediately.
451
+ * Optional validator to check if object is reusable.
452
+ * Return false to discard corrupted objects.
242
453
  */
243
- private handlePing;
454
+ validate?: (obj: T) => boolean;
244
455
  /**
245
- * Checks if a client is still alive based on heartbeat.
456
+ * Initial pool size.
457
+ * Default: 32
246
458
  */
247
- isClientAlive(clientId: string): boolean;
459
+ initialSize?: number;
248
460
  /**
249
- * Returns how long the client has been idle (no PING received).
461
+ * Maximum pool size.
462
+ * Excess objects are discarded.
463
+ * Default: 512
250
464
  */
251
- getClientIdleTime(clientId: string): number;
465
+ maxSize?: number;
252
466
  /**
253
- * Evicts clients that haven't sent a PING within the timeout period.
467
+ * Name for debugging/metrics.
254
468
  */
255
- private evictDeadClients;
256
- private reportLocalHlc;
257
- private handleGcReport;
258
- private performGarbageCollection;
259
- private buildTLSOptions;
469
+ name?: string;
470
+ }
471
+ interface ObjectPoolStats {
472
+ /** Pool name */
473
+ name: string;
474
+ /** Objects currently available */
475
+ available: number;
476
+ /** Objects currently in use */
477
+ inUse: number;
478
+ /** Total objects created */
479
+ created: number;
480
+ /** Total times an object was reused */
481
+ reused: number;
482
+ /** Reuse ratio */
483
+ reuseRatio: number;
484
+ /** Objects discarded (failed validation) */
485
+ discarded: number;
486
+ /** Max pool size */
487
+ maxSize: number;
488
+ /** Peak concurrent usage */
489
+ peakUsage: number;
490
+ }
491
+ /**
492
+ * Generic object pool for reusing plain data structures.
493
+ *
494
+ * Usage:
495
+ * ```typescript
496
+ * const pool = new ObjectPool({
497
+ * factory: () => ({ name: '', value: 0 }),
498
+ * reset: (obj) => { obj.name = ''; obj.value = 0; },
499
+ * });
500
+ *
501
+ * const obj = pool.acquire();
502
+ * obj.name = 'test';
503
+ * obj.value = 42;
504
+ * // ... use obj ...
505
+ * pool.release(obj);
506
+ * ```
507
+ *
508
+ * Important:
509
+ * - Only use for plain data objects
510
+ * - Don't pool objects with closures or event listeners
511
+ * - Don't keep references after release
512
+ */
513
+ declare class ObjectPool<T> {
514
+ private readonly pool;
515
+ private readonly factory;
516
+ private readonly resetFn;
517
+ private readonly validate?;
518
+ private readonly maxSize;
519
+ private readonly name;
520
+ private inUseCount;
521
+ private createdCount;
522
+ private reusedCount;
523
+ private discardedCount;
524
+ private peakUsage;
525
+ private readonly releasedObjects;
526
+ constructor(config: ObjectPoolConfig<T>);
527
+ /**
528
+ * Acquire an object from the pool.
529
+ * Creates new object via factory if pool is empty.
530
+ *
531
+ * @returns A clean, ready-to-use object
532
+ */
533
+ acquire(): T;
534
+ /**
535
+ * Release an object back to the pool.
536
+ * Object is reset before returning to pool.
537
+ *
538
+ * @param obj - The object to release
539
+ */
540
+ release(obj: T): void;
541
+ /**
542
+ * Acquire multiple objects at once.
543
+ * More efficient than multiple acquire() calls.
544
+ *
545
+ * @param count - Number of objects to acquire
546
+ * @returns Array of objects
547
+ */
548
+ acquireBatch(count: number): T[];
549
+ /**
550
+ * Release multiple objects at once.
551
+ *
552
+ * @param objects - Objects to release
553
+ */
554
+ releaseBatch(objects: T[]): void;
555
+ /**
556
+ * Get pool statistics.
557
+ */
558
+ getStats(): ObjectPoolStats;
559
+ /**
560
+ * Clear all objects from pool.
561
+ */
562
+ clear(): void;
563
+ /**
564
+ * Pre-warm pool with objects.
565
+ *
566
+ * @param count - Number of objects to create
567
+ */
568
+ prewarm(count?: number): void;
569
+ /**
570
+ * Reset statistics.
571
+ */
572
+ resetStats(): void;
573
+ private createObject;
260
574
  }
261
575
 
262
- interface PostgresAdapterOptions {
263
- tableName?: string;
576
+ /**
577
+ * MessagePool - Pre-configured ObjectPool for message objects.
578
+ * Phase 2.04: Object Pool Implementation
579
+ *
580
+ * Reduces GC pressure when processing incoming messages.
581
+ */
582
+
583
+ /**
584
+ * Pooled message structure matching common message format.
585
+ */
586
+ interface PooledMessage {
587
+ type: string;
588
+ payload: unknown;
589
+ timestamp: number | null;
590
+ clientId: string | null;
591
+ mapName: string | null;
592
+ key: string | null;
264
593
  }
265
- declare class PostgresAdapter implements IServerStorage {
266
- private pool;
267
- private tableName;
268
- constructor(configOrPool: PoolConfig | Pool, options?: PostgresAdapterOptions);
269
- initialize(): Promise<void>;
270
- close(): Promise<void>;
271
- load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
272
- loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
273
- loadAllKeys(mapName: string): Promise<string[]>;
274
- store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
275
- storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
276
- delete(mapName: string, key: string): Promise<void>;
277
- deleteAll(mapName: string, keys: string[]): Promise<void>;
278
- private mapRowToRecord;
279
- private isORMapValue;
594
+ /**
595
+ * Create a new MessagePool instance.
596
+ *
597
+ * @param config - Pool configuration
598
+ * @returns Configured ObjectPool for messages
599
+ */
600
+ declare function createMessagePool(config?: {
601
+ maxSize?: number;
602
+ initialSize?: number;
603
+ }): ObjectPool<PooledMessage>;
604
+ /**
605
+ * Get or create the global message pool.
606
+ */
607
+ declare function getGlobalMessagePool(): ObjectPool<PooledMessage>;
608
+ /**
609
+ * Replace the global message pool (for testing).
610
+ */
611
+ declare function setGlobalMessagePool(pool: ObjectPool<PooledMessage> | null): void;
612
+
613
+ /**
614
+ * TimestampPool - Pre-configured ObjectPool for HLC timestamp objects.
615
+ * Phase 2.04: Object Pool Implementation
616
+ *
617
+ * Reduces GC pressure for frequent timestamp operations.
618
+ * Timestamps are created on every operation (set, merge, etc.).
619
+ */
620
+
621
+ /**
622
+ * Pooled timestamp structure matching HLC format.
623
+ */
624
+ interface PooledTimestamp {
625
+ millis: number;
626
+ counter: number;
627
+ nodeId: string;
280
628
  }
629
+ /**
630
+ * Create a new TimestampPool instance.
631
+ *
632
+ * @param config - Pool configuration
633
+ * @returns Configured ObjectPool for timestamps
634
+ */
635
+ declare function createTimestampPool(config?: {
636
+ maxSize?: number;
637
+ initialSize?: number;
638
+ }): ObjectPool<PooledTimestamp>;
639
+ /**
640
+ * Get or create the global timestamp pool.
641
+ */
642
+ declare function getGlobalTimestampPool(): ObjectPool<PooledTimestamp>;
643
+ /**
644
+ * Replace the global timestamp pool (for testing).
645
+ */
646
+ declare function setGlobalTimestampPool(pool: ObjectPool<PooledTimestamp> | null): void;
281
647
 
282
648
  /**
283
- * In-memory implementation of IServerStorage.
284
- * Useful for development, testing, and demos without requiring a database.
649
+ * RecordPool - Pre-configured ObjectPool for LWW/OR record objects.
650
+ * Phase 2.04: Object Pool Implementation
285
651
  *
286
- * Note: Data is lost when the server restarts.
652
+ * Reduces GC pressure when processing CRDT operations.
287
653
  */
288
- declare class MemoryServerAdapter implements IServerStorage {
289
- private storage;
290
- initialize(): Promise<void>;
291
- close(): Promise<void>;
292
- private getMap;
293
- load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
294
- loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
295
- loadAllKeys(mapName: string): Promise<string[]>;
296
- store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
297
- storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
298
- delete(mapName: string, key: string): Promise<void>;
299
- deleteAll(mapName: string, keys: string[]): Promise<void>;
654
+
655
+ /**
656
+ * Pooled record structure matching LWWRecord format.
657
+ */
658
+ interface PooledRecord<T = unknown> {
659
+ value: T | null;
660
+ timestamp: PooledTimestamp | null;
661
+ ttlMs?: number;
662
+ }
663
+ /**
664
+ * Pooled event payload structure.
665
+ */
666
+ interface PooledEventPayload {
667
+ mapName: string;
668
+ key: string;
669
+ eventType: string;
670
+ record: PooledRecord | null;
671
+ orRecord: PooledRecord | null;
672
+ orTag: string | null;
300
673
  }
674
+ /**
675
+ * Create a new RecordPool instance.
676
+ *
677
+ * @param config - Pool configuration
678
+ * @returns Configured ObjectPool for records
679
+ */
680
+ declare function createRecordPool<T = unknown>(config?: {
681
+ maxSize?: number;
682
+ initialSize?: number;
683
+ }): ObjectPool<PooledRecord<T>>;
684
+ /**
685
+ * Create a new EventPayloadPool instance.
686
+ *
687
+ * @param config - Pool configuration
688
+ * @returns Configured ObjectPool for event payloads
689
+ */
690
+ declare function createEventPayloadPool(config?: {
691
+ maxSize?: number;
692
+ initialSize?: number;
693
+ }): ObjectPool<PooledEventPayload>;
694
+ /**
695
+ * Get or create the global record pool.
696
+ */
697
+ declare function getGlobalRecordPool(): ObjectPool<PooledRecord>;
698
+ /**
699
+ * Replace the global record pool (for testing).
700
+ */
701
+ declare function setGlobalRecordPool(pool: ObjectPool<PooledRecord> | null): void;
702
+ /**
703
+ * Get or create the global event payload pool.
704
+ */
705
+ declare function getGlobalEventPayloadPool(): ObjectPool<PooledEventPayload>;
706
+ /**
707
+ * Replace the global event payload pool (for testing).
708
+ */
709
+ declare function setGlobalEventPayloadPool(pool: ObjectPool<PooledEventPayload> | null): void;
301
710
 
302
- declare class SecurityManager {
303
- private policies;
304
- constructor(policies?: PermissionPolicy[]);
305
- addPolicy(policy: PermissionPolicy): void;
306
- checkPermission(principal: Principal, mapName: string, action: PermissionType): boolean;
307
- filterObject(object: any, principal: Principal, mapName: string): any;
308
- private hasRole;
309
- private matchesMap;
711
+ /**
712
+ * WorkerPool Types
713
+ * Phase 1.02: Worker Threads Implementation
714
+ */
715
+ /**
716
+ * Configuration for WorkerPool
717
+ */
718
+ interface WorkerPoolConfig {
719
+ /** Minimum number of workers (default: 2) */
720
+ minWorkers?: number;
721
+ /** Maximum number of workers (default: os.cpus().length - 1) */
722
+ maxWorkers?: number;
723
+ /** Task execution timeout in ms (default: 5000) */
724
+ taskTimeout?: number;
725
+ /** Worker idle timeout before termination in ms (default: 30000) */
726
+ idleTimeout?: number;
727
+ /** Enable worker restart on crash (default: true) */
728
+ autoRestart?: boolean;
729
+ /** Custom worker script path (for testing or custom workers) */
730
+ workerScript?: string;
731
+ }
732
+ /**
733
+ * Task types supported by workers
734
+ */
735
+ type WorkerTaskType = 'merkle-hash' | 'merkle-hash-ormap' | 'merkle-diff' | 'merkle-rebuild' | 'merkle-rebuild-ormap' | 'lww-merge' | 'ormap-merge' | 'serialize' | 'deserialize';
736
+ /**
737
+ * Task priority levels
738
+ */
739
+ type TaskPriority = 'high' | 'normal' | 'low';
740
+ /**
741
+ * Task to be executed by a worker
742
+ */
743
+ interface WorkerTask<TPayload = unknown, TResult = unknown> {
744
+ /** Unique task ID */
745
+ id: string;
746
+ /** Task type for routing to correct handler */
747
+ type: WorkerTaskType;
748
+ /** Task payload (must be serializable) */
749
+ payload: TPayload;
750
+ /** Priority (default: 'normal') */
751
+ priority?: TaskPriority;
752
+ /** Internal: Expected result type marker */
753
+ _resultType?: TResult;
754
+ }
755
+ /**
756
+ * Pool statistics
757
+ */
758
+ interface WorkerPoolStats {
759
+ /** Number of workers currently executing tasks */
760
+ activeWorkers: number;
761
+ /** Number of workers waiting for tasks */
762
+ idleWorkers: number;
763
+ /** Number of tasks in queue */
764
+ pendingTasks: number;
765
+ /** Total tasks completed successfully */
766
+ completedTasks: number;
767
+ /** Total tasks that failed */
768
+ failedTasks: number;
769
+ /** Average task execution time in ms */
770
+ avgTaskDuration: number;
310
771
  }
311
772
 
312
- declare const logger: pino.Logger<never, boolean>;
313
- type Logger = typeof logger;
773
+ /**
774
+ * WorkerPool Implementation
775
+ * Phase 1.02: Worker Threads Implementation
776
+ *
777
+ * Manages a pool of worker threads for CPU-bound operations.
778
+ * Features:
779
+ * - Auto-scaling (minWorkers to maxWorkers)
780
+ * - Priority queue (high > normal > low)
781
+ * - Task timeouts
782
+ * - Worker crash recovery
783
+ * - Graceful shutdown
784
+ */
314
785
 
315
- declare class TimestampInterceptor implements IInterceptor {
316
- name: string;
317
- onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp>;
786
+ declare class WorkerPool {
787
+ private readonly config;
788
+ private readonly workers;
789
+ private readonly taskQueue;
790
+ private readonly pendingTasks;
791
+ private workerIdCounter;
792
+ private isShuttingDown;
793
+ private isShutdown;
794
+ private completedTaskCount;
795
+ private failedTaskCount;
796
+ private totalTaskDuration;
797
+ private idleCheckInterval?;
798
+ constructor(config?: WorkerPoolConfig);
799
+ /**
800
+ * Resolve the worker script path based on environment
801
+ */
802
+ private resolveWorkerScript;
803
+ /**
804
+ * Submit a task to the pool
805
+ */
806
+ submit<TPayload, TResult>(task: WorkerTask<TPayload, TResult>): Promise<TResult>;
807
+ /**
808
+ * Get current pool statistics
809
+ */
810
+ getStats(): WorkerPoolStats;
811
+ /**
812
+ * Gracefully shutdown all workers
813
+ */
814
+ shutdown(timeout?: number): Promise<void>;
815
+ /**
816
+ * Check if pool is accepting tasks
817
+ */
818
+ isRunning(): boolean;
819
+ private initializeWorkers;
820
+ private createWorker;
821
+ private findIdleWorker;
822
+ private assignTaskToWorker;
823
+ private enqueueTask;
824
+ private tryScaleUp;
825
+ private handleWorkerResponse;
826
+ private handleTaskTimeout;
827
+ private handleWorkerError;
828
+ private handleWorkerExit;
829
+ private startIdleCheck;
830
+ private checkIdleWorkers;
318
831
  }
319
832
 
320
- interface RateLimitConfig {
321
- windowMs: number;
322
- maxOps: number;
833
+ /**
834
+ * Merkle Worker Types
835
+ * Phase 1.03: MerkleWorker Implementation
836
+ */
837
+
838
+ /**
839
+ * Entry for Merkle hash computation (LWWMap style)
840
+ */
841
+ interface MerkleHashEntry {
842
+ key: string;
843
+ timestamp: Timestamp;
323
844
  }
324
- declare class RateLimitInterceptor implements IInterceptor {
325
- name: string;
326
- private limits;
327
- private config;
328
- constructor(config?: RateLimitConfig);
329
- onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
330
- onDisconnect(context: any): Promise<void>;
845
+ /**
846
+ * Entry for ORMap Merkle hash computation
847
+ */
848
+ interface ORMapMerkleHashEntry {
849
+ key: string;
850
+ records: Array<{
851
+ tag: string;
852
+ timestamp: Timestamp;
853
+ }>;
854
+ }
855
+ /**
856
+ * Payload for merkle-hash task (LWWMap)
857
+ */
858
+ interface MerkleHashPayload {
859
+ entries: MerkleHashEntry[];
860
+ depth?: number;
861
+ }
862
+ /**
863
+ * Result of merkle-hash task
864
+ */
865
+ interface MerkleHashResult {
866
+ /** Map of key -> hash for each entry */
867
+ hashes: Array<[string, number]>;
868
+ /** Root hash of all entries */
869
+ rootHash: number;
870
+ /** Bucket structure: path -> { hash, keys } */
871
+ buckets: Array<[string, {
872
+ hash: number;
873
+ keys: string[];
874
+ }]>;
875
+ }
876
+ /**
877
+ * Payload for merkle-hash-ormap task
878
+ */
879
+ interface ORMapMerkleHashPayload {
880
+ entries: ORMapMerkleHashEntry[];
881
+ depth?: number;
882
+ }
883
+ /**
884
+ * Result of merkle-hash-ormap task
885
+ */
886
+ interface ORMapMerkleHashResult {
887
+ /** Map of key -> hash for each entry */
888
+ hashes: Array<[string, number]>;
889
+ /** Root hash of all entries */
890
+ rootHash: number;
891
+ /** Bucket structure: path -> { hash, keys } */
892
+ buckets: Array<[string, {
893
+ hash: number;
894
+ keys: string[];
895
+ }]>;
896
+ }
897
+ /**
898
+ * Bucket info for diff comparison
899
+ */
900
+ interface BucketInfo {
901
+ hash: number;
902
+ keys: string[];
903
+ }
904
+ /**
905
+ * Payload for merkle-diff task
906
+ */
907
+ interface MerkleDiffPayload {
908
+ /** Local buckets: path -> bucket info */
909
+ localBuckets: Array<[string, BucketInfo]>;
910
+ /** Remote buckets: path -> bucket info */
911
+ remoteBuckets: Array<[string, BucketInfo]>;
912
+ }
913
+ /**
914
+ * Result of merkle-diff task
915
+ */
916
+ interface MerkleDiffResult {
917
+ /** Keys that exist on remote but not locally */
918
+ missingLocal: string[];
919
+ /** Keys that exist locally but not on remote */
920
+ missingRemote: string[];
921
+ /** Paths where buckets differ (need deeper comparison) */
922
+ differingPaths: string[];
923
+ }
924
+ /**
925
+ * Payload for merkle-rebuild task (LWWMap)
926
+ */
927
+ interface MerkleRebuildPayload {
928
+ records: Array<{
929
+ key: string;
930
+ timestamp: Timestamp;
931
+ }>;
932
+ depth?: number;
933
+ }
934
+ /**
935
+ * Payload for merkle-rebuild-ormap task
936
+ */
937
+ interface ORMapMerkleRebuildPayload {
938
+ records: Array<{
939
+ key: string;
940
+ tags: Array<{
941
+ tag: string;
942
+ timestamp: Timestamp;
943
+ }>;
944
+ }>;
945
+ depth?: number;
946
+ }
947
+ /**
948
+ * Result of merkle-rebuild task
949
+ */
950
+ interface MerkleRebuildResult {
951
+ /** Root hash of rebuilt tree */
952
+ rootHash: number;
953
+ /** All buckets in the tree */
954
+ buckets: Array<[string, {
955
+ hash: number;
956
+ keys: string[];
957
+ }]>;
958
+ }
959
+
960
+ /**
961
+ * MerkleWorker - High-level API for Merkle tree operations in worker threads
962
+ * Phase 1.03: MerkleWorker Implementation
963
+ *
964
+ * Provides a clean interface for CPU-intensive Merkle tree operations.
965
+ * Delegates actual work to worker threads via WorkerPool.
966
+ */
967
+
968
+ /**
969
+ * MerkleWorker provides methods for Merkle tree operations.
970
+ * Automatically decides whether to use worker threads based on workload size.
971
+ */
972
+ declare class MerkleWorker {
973
+ private readonly pool;
974
+ private readonly workerScript;
975
+ constructor(pool: WorkerPool);
976
+ private resolveMerkleWorkerScript;
977
+ /**
978
+ * Compute hashes for a batch of LWWMap entries.
979
+ * Uses worker thread if entries count exceeds threshold.
980
+ */
981
+ computeHashes(payload: MerkleHashPayload): Promise<MerkleHashResult>;
982
+ /**
983
+ * Compute hashes for a batch of ORMap entries.
984
+ * Uses worker thread if entries count exceeds threshold.
985
+ */
986
+ computeORMapHashes(payload: ORMapMerkleHashPayload): Promise<ORMapMerkleHashResult>;
987
+ /**
988
+ * Find differences between local and remote Merkle trees.
989
+ */
990
+ diff(payload: MerkleDiffPayload): Promise<MerkleDiffResult>;
991
+ /**
992
+ * Rebuild Merkle tree from LWWMap records.
993
+ * Always uses worker thread as this is typically a heavy operation.
994
+ */
995
+ rebuild(payload: MerkleRebuildPayload): Promise<MerkleRebuildResult>;
996
+ /**
997
+ * Rebuild Merkle tree from ORMap records.
998
+ */
999
+ rebuildORMap(payload: ORMapMerkleRebuildPayload): Promise<MerkleRebuildResult>;
1000
+ private computeHashesInline;
1001
+ private computeORMapHashesInline;
1002
+ private diffInline;
1003
+ private rebuildInline;
1004
+ private rebuildORMapInline;
1005
+ private hashString;
1006
+ private buildTree;
1007
+ }
1008
+
1009
+ /**
1010
+ * CRDT Worker Types
1011
+ * Phase 1.04: CRDTMergeWorker Implementation
1012
+ */
1013
+
1014
+ /**
1015
+ * Single LWW record for merge
1016
+ */
1017
+ interface LWWMergeRecord {
1018
+ key: string;
1019
+ value: unknown;
1020
+ timestamp: Timestamp;
1021
+ ttlMs?: number;
1022
+ }
1023
+ /**
1024
+ * Existing state for a key (for merge comparison)
1025
+ * Note: value is optional since we only need timestamp for comparison
1026
+ */
1027
+ interface LWWExistingRecord {
1028
+ key: string;
1029
+ timestamp: Timestamp;
1030
+ value?: unknown;
1031
+ ttlMs?: number;
1032
+ }
1033
+ /**
1034
+ * Payload for lww-merge task
1035
+ */
1036
+ interface LWWMergePayload {
1037
+ mapName: string;
1038
+ /** Records to merge */
1039
+ records: LWWMergeRecord[];
1040
+ /** Current state of affected keys (for comparison) */
1041
+ existingState: LWWExistingRecord[];
1042
+ }
1043
+ /**
1044
+ * Result of lww-merge task
1045
+ */
1046
+ interface LWWMergeResult {
1047
+ /** Records that should be applied (newer than existing) */
1048
+ toApply: Array<{
1049
+ key: string;
1050
+ value: unknown;
1051
+ timestamp: Timestamp;
1052
+ ttlMs?: number;
1053
+ }>;
1054
+ /** Number of records skipped (older timestamp) */
1055
+ skipped: number;
1056
+ /** Keys with concurrent updates (same timestamp, different nodeId) */
1057
+ conflicts: string[];
1058
+ }
1059
+ /**
1060
+ * Single ORMap item for merge
1061
+ */
1062
+ interface ORMapMergeItem {
1063
+ key: string;
1064
+ value: unknown;
1065
+ timestamp: Timestamp;
1066
+ tag: string;
1067
+ ttlMs?: number;
1068
+ }
1069
+ /**
1070
+ * Single ORMap tombstone for merge
1071
+ */
1072
+ interface ORMapMergeTombstone {
1073
+ tag: string;
1074
+ timestamp: Timestamp;
1075
+ }
1076
+ /**
1077
+ * Payload for ormap-merge task
1078
+ */
1079
+ interface ORMapMergePayload {
1080
+ mapName: string;
1081
+ /** Items to merge */
1082
+ items: ORMapMergeItem[];
1083
+ /** Tombstones to merge */
1084
+ tombstones: ORMapMergeTombstone[];
1085
+ /** Existing tags in the map (for tombstone check) */
1086
+ existingTags: string[];
1087
+ /** Existing tombstones (to avoid re-adding deleted items) */
1088
+ existingTombstones: string[];
1089
+ }
1090
+ /**
1091
+ * Result of ormap-merge task
1092
+ */
1093
+ interface ORMapMergeResult {
1094
+ /** Items that should be applied */
1095
+ itemsToApply: Array<{
1096
+ key: string;
1097
+ value: unknown;
1098
+ timestamp: Timestamp;
1099
+ tag: string;
1100
+ ttlMs?: number;
1101
+ }>;
1102
+ /** Tombstones that should be applied */
1103
+ tombstonesToApply: string[];
1104
+ /** Tags that need to be removed due to new tombstones */
1105
+ tagsToRemove: string[];
1106
+ /** Number of items skipped */
1107
+ itemsSkipped: number;
1108
+ /** Number of tombstones skipped */
1109
+ tombstonesSkipped: number;
1110
+ }
1111
+
1112
+ /**
1113
+ * CRDTMergeWorker - High-level API for CRDT merge operations in worker threads
1114
+ * Phase 1.04: CRDTMergeWorker Implementation
1115
+ *
1116
+ * Provides a clean interface for CPU-intensive CRDT merge operations.
1117
+ * Delegates actual work to worker threads via WorkerPool for large batches.
1118
+ */
1119
+
1120
+ /**
1121
+ * CRDTMergeWorker provides methods for CRDT merge operations.
1122
+ * Automatically decides whether to use worker threads based on batch size.
1123
+ */
1124
+ declare class CRDTMergeWorker {
1125
+ private readonly pool;
1126
+ /** Threshold for using worker (operations below this go to main thread) */
1127
+ static readonly BATCH_THRESHOLD = 10;
1128
+ constructor(pool: WorkerPool);
1129
+ /**
1130
+ * Decide if batch should go to worker
1131
+ */
1132
+ shouldUseWorker(batchSize: number): boolean;
1133
+ /**
1134
+ * Merge LWW records
1135
+ * @param payload - Records to merge and existing state
1136
+ * @returns Which records should be applied
1137
+ */
1138
+ mergeLWW(payload: LWWMergePayload): Promise<LWWMergeResult>;
1139
+ /**
1140
+ * Merge ORMap items and tombstones
1141
+ * @param payload - Items, tombstones, and existing state
1142
+ * @returns Which items/tombstones should be applied
1143
+ */
1144
+ mergeORMap(payload: ORMapMergePayload): Promise<ORMapMergeResult>;
1145
+ private mergeLWWInline;
1146
+ private mergeORMapInline;
1147
+ }
1148
+
1149
+ /**
1150
+ * SerializationWorker - High-level API for serialization operations in worker threads
1151
+ * Phase 1.07: SerializationWorker Implementation
1152
+ *
1153
+ * Provides a clean interface for CPU-intensive serialization/deserialization.
1154
+ * Delegates actual work to worker threads via WorkerPool for large payloads.
1155
+ *
1156
+ * Uses base64 encoding to transfer binary data through postMessage.
1157
+ * This adds ~33% overhead but is necessary since Uint8Array cannot be
1158
+ * directly transferred through structured clone algorithm for our use case.
1159
+ */
1160
+
1161
+ /**
1162
+ * SerializationWorker provides methods for serialization operations.
1163
+ * Automatically decides whether to use worker threads based on payload size.
1164
+ */
1165
+ declare class SerializationWorker {
1166
+ private readonly pool;
1167
+ private readonly workerScript;
1168
+ /** Threshold for using worker (items below this go to main thread) */
1169
+ static readonly BATCH_THRESHOLD = 10;
1170
+ /** Size threshold for using worker (bytes) */
1171
+ static readonly SIZE_THRESHOLD: number;
1172
+ constructor(pool: WorkerPool);
1173
+ private resolveWorkerScript;
1174
+ /**
1175
+ * Decide if batch should go to worker based on count or size
1176
+ */
1177
+ shouldUseWorker(items: unknown[]): boolean;
1178
+ /**
1179
+ * Serialize multiple objects to MessagePack binary format.
1180
+ * Uses worker thread for large batches.
1181
+ *
1182
+ * @param items - Objects to serialize
1183
+ * @returns Array of Uint8Array containing serialized data
1184
+ */
1185
+ serializeBatch(items: unknown[]): Promise<Uint8Array[]>;
1186
+ /**
1187
+ * Deserialize multiple MessagePack binary payloads to objects.
1188
+ * Uses worker thread for large batches.
1189
+ *
1190
+ * @param items - Binary data to deserialize
1191
+ * @returns Array of deserialized objects
1192
+ */
1193
+ deserializeBatch<T = unknown>(items: Uint8Array[]): Promise<T[]>;
1194
+ /**
1195
+ * Serialize a single object (always inline, too small for worker)
1196
+ */
1197
+ serialize(data: unknown): Uint8Array;
1198
+ /**
1199
+ * Deserialize a single payload (always inline, too small for worker)
1200
+ */
1201
+ deserialize<T = unknown>(data: Uint8Array | ArrayBuffer): T;
1202
+ private serializeBatchInline;
1203
+ private deserializeBatchInline;
1204
+ }
1205
+
1206
+ /**
1207
+ * SharedMemoryManager - Zero-copy data transfer between main thread and workers
1208
+ *
1209
+ * Uses SharedArrayBuffer with Atomics for synchronization.
1210
+ * Provides slot-based allocation for concurrent operations.
1211
+ *
1212
+ * Phase 3.04: SharedArrayBuffer Integration
1213
+ */
1214
+ interface SharedMemoryConfig {
1215
+ /**
1216
+ * Size of shared buffer in bytes.
1217
+ * Default: 16MB
1218
+ */
1219
+ bufferSize?: number;
1220
+ /**
1221
+ * Number of slots for concurrent operations.
1222
+ * Each slot can hold one transfer.
1223
+ * Default: 256
1224
+ */
1225
+ slotCount?: number;
1226
+ /**
1227
+ * Reserved bytes per slot for metadata (length, status, etc).
1228
+ * Default: 16 (must be multiple of 8 for alignment)
1229
+ */
1230
+ metadataSize?: number;
1231
+ }
1232
+ interface SharedMemoryStats {
1233
+ /** Total buffer size in bytes */
1234
+ totalSize: number;
1235
+ /** Number of slots */
1236
+ slotCount: number;
1237
+ /** Size of each slot in bytes */
1238
+ slotSize: number;
1239
+ /** Currently allocated slots */
1240
+ allocatedSlots: number;
1241
+ /** Available slots */
1242
+ availableSlots: number;
1243
+ /** Peak concurrent allocations */
1244
+ peakUsage: number;
1245
+ /** Total allocations since creation */
1246
+ totalAllocations: number;
1247
+ /** Total releases since creation */
1248
+ totalReleases: number;
1249
+ }
1250
+ interface SharedSlot {
1251
+ /** Slot index */
1252
+ index: number;
1253
+ /** View into shared buffer for this slot's data area */
1254
+ dataView: Uint8Array;
1255
+ /** Maximum data size (excluding metadata) */
1256
+ maxDataSize: number;
1257
+ }
1258
+ /**
1259
+ * Slot status values (stored in first 4 bytes of slot metadata)
1260
+ */
1261
+ declare enum SlotStatus {
1262
+ FREE = 0,// Slot is available
1263
+ ALLOCATED = 1,// Slot is allocated, no data yet
1264
+ DATA_READY = 2,// Data written, ready for reading
1265
+ PROCESSING = 3,// Worker is processing
1266
+ RESULT_READY = 4,// Worker has written result
1267
+ ERROR = 255
1268
+ }
1269
+ /**
1270
+ * Manages shared memory for zero-copy data transfer between threads.
1271
+ *
1272
+ * Usage:
1273
+ * 1. Main thread allocates a slot
1274
+ * 2. Main thread writes data to slot
1275
+ * 3. Main thread sends slot index to worker via postMessage
1276
+ * 4. Worker reads data from shared memory (zero-copy)
1277
+ * 5. Worker writes result to slot
1278
+ * 6. Main thread reads result (zero-copy)
1279
+ * 7. Main thread releases slot
1280
+ */
1281
+ declare class SharedMemoryManager {
1282
+ private readonly buffer;
1283
+ private readonly statusArray;
1284
+ private readonly slotSize;
1285
+ private readonly slotCount;
1286
+ private readonly metadataSize;
1287
+ private readonly freeSlots;
1288
+ private allocatedCount;
1289
+ private peakUsage;
1290
+ private totalAllocations;
1291
+ private totalReleases;
1292
+ constructor(config?: SharedMemoryConfig);
1293
+ /**
1294
+ * Get offset in Int32Array for slot status.
1295
+ * Status is at the beginning of each slot's metadata.
1296
+ */
1297
+ private getStatusOffset;
1298
+ /**
1299
+ * Get byte offset for slot length field.
1300
+ */
1301
+ private getLengthOffset;
1302
+ /**
1303
+ * Get byte offset for slot data (after metadata).
1304
+ */
1305
+ private getDataOffset;
1306
+ /**
1307
+ * Allocate a slot for data transfer.
1308
+ * Returns null if no slots available.
1309
+ */
1310
+ allocate(): SharedSlot | null;
1311
+ /**
1312
+ * Release a slot back to the pool.
1313
+ */
1314
+ release(slot: SharedSlot): void;
1315
+ /**
1316
+ * Write data to a slot and signal it's ready.
1317
+ * Returns false if data is too large.
1318
+ */
1319
+ writeData(slot: SharedSlot, data: Uint8Array): boolean;
1320
+ /**
1321
+ * Read data length from a slot.
1322
+ */
1323
+ getDataLength(slotIndex: number): number;
1324
+ /**
1325
+ * Get data view for a slot (for reading).
1326
+ */
1327
+ getDataView(slotIndex: number): Uint8Array;
1328
+ /**
1329
+ * Get slot status.
1330
+ */
1331
+ getStatus(slotIndex: number): SlotStatus;
1332
+ /**
1333
+ * Wait for a specific status with timeout.
1334
+ * Returns the actual status (may differ if timeout occurred).
1335
+ */
1336
+ waitForStatus(slotIndex: number, expectedStatus: SlotStatus, timeoutMs?: number): SlotStatus;
1337
+ /**
1338
+ * Wait for result and read it.
1339
+ * Returns null on timeout or error.
1340
+ */
1341
+ waitForResult(slot: SharedSlot, timeoutMs?: number): Uint8Array | null;
1342
+ /**
1343
+ * Get the SharedArrayBuffer for passing to workers.
1344
+ */
1345
+ getBuffer(): SharedArrayBuffer;
1346
+ /**
1347
+ * Get configuration needed by workers.
1348
+ */
1349
+ getWorkerConfig(): SharedWorkerConfig;
1350
+ /**
1351
+ * Get statistics.
1352
+ */
1353
+ getStats(): SharedMemoryStats;
1354
+ /**
1355
+ * Check if SharedArrayBuffer is available in current environment.
1356
+ */
1357
+ static isAvailable(): boolean;
1358
+ /**
1359
+ * Shutdown and release resources.
1360
+ * Resets all slots to FREE status.
1361
+ */
1362
+ shutdown(): void;
1363
+ }
1364
+ /**
1365
+ * Configuration passed to workers for shared memory access.
1366
+ */
1367
+ interface SharedWorkerConfig {
1368
+ sharedBuffer: SharedArrayBuffer;
1369
+ slotSize: number;
1370
+ slotCount: number;
1371
+ metadataSize: number;
1372
+ }
1373
+
1374
+ interface QueueMetrics {
1375
+ enqueued: number;
1376
+ dequeued: number;
1377
+ rejected: number;
1378
+ currentSize: number;
1379
+ }
1380
+
1381
+ interface StripeMetrics {
1382
+ stripe: number;
1383
+ metrics: QueueMetrics;
1384
+ }
1385
+
1386
+ type ORMapValue<V> = {
1387
+ type: 'OR';
1388
+ records: ORMapRecord<V>[];
1389
+ };
1390
+ type ORMapTombstones = {
1391
+ type: 'OR_TOMBSTONES';
1392
+ tags: string[];
1393
+ };
1394
+ type StorageValue<V> = LWWRecord<V> | ORMapValue<V> | ORMapTombstones;
1395
+ /**
1396
+ * Server Persistence Interface (MapStore).
1397
+ * Aligned with specifications/06_SERVER_INTEGRATIONS.md
1398
+ *
1399
+ * Note: We include mapName in all methods because a single storage adapter
1400
+ * instance typically handles multiple maps in the system (e.g. single DB connection).
1401
+ */
1402
+ interface IServerStorage {
1403
+ /**
1404
+ * Initialize the storage connection.
1405
+ */
1406
+ initialize(): Promise<void>;
1407
+ /**
1408
+ * Close the storage connection.
1409
+ */
1410
+ close(): Promise<void>;
1411
+ /**
1412
+ * Loads the value of a given key.
1413
+ * Called when a client requests a key that is not in the Server RAM (if using partial loading),
1414
+ * or during sync.
1415
+ */
1416
+ load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
1417
+ /**
1418
+ * Loads multiple keys.
1419
+ * Optimization for batch requests.
1420
+ */
1421
+ loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
1422
+ /**
1423
+ * Loads all keys from the store for a specific map.
1424
+ * Used for pre-loading the cache on startup or understanding dataset size.
1425
+ */
1426
+ loadAllKeys(mapName: string): Promise<string[]>;
1427
+ /**
1428
+ * Stores the key-value pair.
1429
+ */
1430
+ store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
1431
+ /**
1432
+ * Stores multiple entries.
1433
+ * Used for efficient batch writes to the DB.
1434
+ */
1435
+ storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
1436
+ /**
1437
+ * Deletes the entry with the given key.
1438
+ */
1439
+ delete(mapName: string, key: string): Promise<void>;
1440
+ /**
1441
+ * Deletes multiple entries.
1442
+ */
1443
+ deleteAll(mapName: string, keys: string[]): Promise<void>;
1444
+ }
1445
+
1446
+ interface ServerOp {
1447
+ mapName: string;
1448
+ key: string;
1449
+ opType: 'PUT' | 'REMOVE' | 'OR_ADD' | 'OR_REMOVE';
1450
+ record?: LWWRecord<any>;
1451
+ orRecord?: ORMapRecord<any>;
1452
+ orTag?: string;
1453
+ id?: string;
1454
+ }
1455
+ interface ConnectionContext {
1456
+ clientId: string;
1457
+ socket?: WebSocket;
1458
+ principal?: Principal;
1459
+ isAuthenticated: boolean;
1460
+ }
1461
+ interface OpContext extends ConnectionContext {
1462
+ fromCluster: boolean;
1463
+ originalSenderId?: string;
1464
+ }
1465
+ interface IInterceptor {
1466
+ /**
1467
+ * Name of the interceptor for logging and debugging.
1468
+ */
1469
+ name: string;
1470
+ /**
1471
+ * Called when a new client connects.
1472
+ * Throwing an error here will reject the connection.
1473
+ */
1474
+ onConnection?(context: ConnectionContext): Promise<void>;
1475
+ /**
1476
+ * Called when a client disconnects.
1477
+ */
1478
+ onDisconnect?(context: ConnectionContext): Promise<void>;
1479
+ /**
1480
+ * Called before an operation is applied to the local map/storage.
1481
+ * Return the (possibly modified) op.
1482
+ * Return null to silently drop the operation (no error sent to client, no persistence).
1483
+ * Throwing an error will reject the operation and notify the client.
1484
+ */
1485
+ onBeforeOp?(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
1486
+ /**
1487
+ * Called after an operation has been successfully applied and stored.
1488
+ */
1489
+ onAfterOp?(op: ServerOp, context: OpContext): Promise<void>;
1490
+ }
1491
+
1492
+ interface TLSConfig {
1493
+ /**
1494
+ * Enable TLS for client-facing server (HTTPS + WSS)
1495
+ * @default false
1496
+ */
1497
+ enabled: boolean;
1498
+ /**
1499
+ * Path to certificate file (PEM format)
1500
+ * Supports chain certificates
1501
+ */
1502
+ certPath: string;
1503
+ /**
1504
+ * Path to private key file (PEM format)
1505
+ */
1506
+ keyPath: string;
1507
+ /**
1508
+ * Path to CA certificate for verifying client certificates
1509
+ * Required for mTLS
1510
+ * @optional
1511
+ */
1512
+ caCertPath?: string;
1513
+ /**
1514
+ * Minimum TLS version
1515
+ * @default 'TLSv1.2'
1516
+ */
1517
+ minVersion?: 'TLSv1.2' | 'TLSv1.3';
1518
+ /**
1519
+ * List of allowed cipher suites
1520
+ * @optional - use Node.js defaults if not specified
1521
+ */
1522
+ ciphers?: string;
1523
+ /**
1524
+ * Passphrase for encrypted private key
1525
+ * @optional
1526
+ */
1527
+ passphrase?: string;
1528
+ }
1529
+ interface ClusterTLSConfig extends TLSConfig {
1530
+ /**
1531
+ * Require client certificate (mTLS)
1532
+ * @default false
1533
+ */
1534
+ requireClientCert?: boolean;
1535
+ /**
1536
+ * Verify peer certificates
1537
+ * Can be disabled in development for self-signed certs
1538
+ * @default true
1539
+ */
1540
+ rejectUnauthorized?: boolean;
1541
+ }
1542
+
1543
+ interface CoalescingWriterOptions {
1544
+ /**
1545
+ * Maximum messages to batch before forcing flush.
1546
+ * Default: 100
1547
+ */
1548
+ maxBatchSize: number;
1549
+ /**
1550
+ * Maximum time to wait before flushing (ms).
1551
+ * Default: 5 (similar to Nagle's algorithm)
1552
+ */
1553
+ maxDelayMs: number;
1554
+ /**
1555
+ * Maximum batch size in bytes.
1556
+ * Default: 65536 (64KB)
1557
+ */
1558
+ maxBatchBytes: number;
1559
+ /**
1560
+ * Optional BufferPool for batch buffer reuse.
1561
+ * If not provided, uses the global buffer pool.
1562
+ */
1563
+ bufferPool?: BufferPool;
1564
+ }
1565
+ /**
1566
+ * Extended metrics for CoalescingWriter performance analysis.
1567
+ */
1568
+ interface CoalescingWriterMetrics {
1569
+ /** Total messages sent */
1570
+ messagesSent: number;
1571
+ /** Total batches sent */
1572
+ batchesSent: number;
1573
+ /** Total bytes sent */
1574
+ bytesSent: number;
1575
+ /** Average messages per batch */
1576
+ avgMessagesPerBatch: number;
1577
+ /** Average bytes per batch */
1578
+ avgBytesPerBatch: number;
1579
+ /** Messages currently in queue */
1580
+ pendingMessages: number;
1581
+ /** Bytes currently pending */
1582
+ pendingBytes: number;
1583
+ /** Count of flushes triggered by size limits (batch full or bytes exceeded) */
1584
+ immediateFlushes: number;
1585
+ /** Count of flushes triggered by timer expiration */
1586
+ timedFlushes: number;
1587
+ /** Ratio of actual batch size to maxBatchSize (0-1, higher = better utilization) */
1588
+ batchUtilization: number;
1589
+ /** Ratio of immediate flushes to total flushes (high = batches filling up quickly) */
1590
+ immediateFlushRatio: number;
1591
+ /** Count of pooled buffer acquisitions (for monitoring buffer pool usage) */
1592
+ pooledBuffersUsed: number;
1593
+ /** Count of oversized (non-pooled) buffers that were allocated directly */
1594
+ oversizedBuffers: number;
1595
+ }
1596
+
1597
+ /**
1598
+ * Preset configurations for CoalescingWriter.
1599
+ * Based on Hazelcast OutboxImpl (batch size 2048) and real-world benchmarking.
1600
+ *
1601
+ * Trade-offs:
1602
+ * - Larger batch size = higher throughput, higher latency
1603
+ * - Longer delay = more messages per batch, higher latency
1604
+ * - Larger maxBatchBytes = handles larger payloads, more memory
1605
+ *
1606
+ * NOTE: A/B testing (Dec 2024) showed maxDelayMs is the primary bottleneck:
1607
+ * - 10ms delay: ~10K ops/sec, p50=11ms
1608
+ * - 1ms delay: ~18K ops/sec, p50=8ms (+80% throughput)
1609
+ * - 0ms (disabled): ~18K ops/sec, p50=2ms (best latency)
1610
+ */
1611
+ declare const coalescingPresets: {
1612
+ /**
1613
+ * Low latency - optimized for minimal response time.
1614
+ * Best for: gaming, real-time chat, interactive applications.
1615
+ * Benchmark: p50=2ms, ~18K ops/sec
1616
+ */
1617
+ readonly lowLatency: {
1618
+ readonly maxBatchSize: 100;
1619
+ readonly maxDelayMs: 1;
1620
+ readonly maxBatchBytes: 65536;
1621
+ };
1622
+ /**
1623
+ * Conservative - good balance of latency and batching.
1624
+ * Use for: general purpose with latency sensitivity.
1625
+ */
1626
+ readonly conservative: {
1627
+ readonly maxBatchSize: 100;
1628
+ readonly maxDelayMs: 2;
1629
+ readonly maxBatchBytes: 65536;
1630
+ };
1631
+ /**
1632
+ * Balanced - good for most workloads.
1633
+ * Reasonable trade-off between throughput and latency.
1634
+ * Use for: mixed read/write applications, general purpose.
1635
+ */
1636
+ readonly balanced: {
1637
+ readonly maxBatchSize: 300;
1638
+ readonly maxDelayMs: 2;
1639
+ readonly maxBatchBytes: 131072;
1640
+ };
1641
+ /**
1642
+ * High throughput - optimized for write-heavy workloads.
1643
+ * Higher batching for better network utilization.
1644
+ * Use for: data ingestion, logging, IoT data streams.
1645
+ * Benchmark: p50=7ms, ~18K ops/sec
1646
+ */
1647
+ readonly highThroughput: {
1648
+ readonly maxBatchSize: 500;
1649
+ readonly maxDelayMs: 2;
1650
+ readonly maxBatchBytes: 262144;
1651
+ };
1652
+ /**
1653
+ * Aggressive - maximum batching for batch processing.
1654
+ * Closest to Hazelcast's OutboxImpl (batch size 2048).
1655
+ * Use for: batch imports, bulk operations, offline sync.
1656
+ */
1657
+ readonly aggressive: {
1658
+ readonly maxBatchSize: 1000;
1659
+ readonly maxDelayMs: 5;
1660
+ readonly maxBatchBytes: 524288;
1661
+ };
1662
+ };
1663
+ /**
1664
+ * Available preset names for type safety.
1665
+ */
1666
+ type CoalescingPreset = keyof typeof coalescingPresets;
1667
+ /**
1668
+ * Get preset configuration by name.
1669
+ * @param preset - Preset name
1670
+ * @returns CoalescingWriterOptions
1671
+ */
1672
+ declare function getCoalescingPreset(preset: CoalescingPreset): CoalescingWriterOptions;
1673
+
1674
+ interface ServerCoordinatorConfig {
1675
+ port: number;
1676
+ nodeId: string;
1677
+ storage?: IServerStorage;
1678
+ jwtSecret?: string;
1679
+ host?: string;
1680
+ clusterPort?: number;
1681
+ peers?: string[];
1682
+ securityPolicies?: PermissionPolicy[];
1683
+ /** Callback to resolve dynamic peer addresses after ports are known */
1684
+ resolvePeers?: () => string[];
1685
+ interceptors?: IInterceptor[];
1686
+ metricsPort?: number;
1687
+ discovery?: 'manual' | 'kubernetes';
1688
+ serviceName?: string;
1689
+ discoveryInterval?: number;
1690
+ tls?: TLSConfig;
1691
+ clusterTls?: ClusterTLSConfig;
1692
+ /** Total event queue capacity for bounded queue (default: 10000) */
1693
+ eventQueueCapacity?: number;
1694
+ /** Number of event queue stripes for parallel processing (default: 4) */
1695
+ eventStripeCount?: number;
1696
+ /** Enable/disable backpressure (default: true) */
1697
+ backpressureEnabled?: boolean;
1698
+ /** How often to force sync processing (default: 100 operations) */
1699
+ backpressureSyncFrequency?: number;
1700
+ /** Maximum pending async operations before blocking (default: 1000) */
1701
+ backpressureMaxPending?: number;
1702
+ /** Backoff timeout in ms when at capacity (default: 5000) */
1703
+ backpressureBackoffMs?: number;
1704
+ /** Enable/disable write coalescing (default: true) */
1705
+ writeCoalescingEnabled?: boolean;
1706
+ /** Coalescing preset: 'conservative', 'balanced', 'highThroughput', 'aggressive' (default: 'highThroughput') */
1707
+ writeCoalescingPreset?: CoalescingPreset;
1708
+ /** Maximum messages to batch before forcing flush (default: 500 for highThroughput) */
1709
+ writeCoalescingMaxBatch?: number;
1710
+ /** Maximum delay before flushing in ms (default: 10 for highThroughput) */
1711
+ writeCoalescingMaxDelayMs?: number;
1712
+ /** Maximum batch size in bytes (default: 262144/256KB for highThroughput) */
1713
+ writeCoalescingMaxBytes?: number;
1714
+ /** WebSocket backlog for pending connections (default: 511) */
1715
+ wsBacklog?: number;
1716
+ /** Enable WebSocket per-message compression (default: false for CPU savings) */
1717
+ wsCompression?: boolean;
1718
+ /** Maximum WebSocket payload size in bytes (default: 64MB) */
1719
+ wsMaxPayload?: number;
1720
+ /** Maximum server connections (default: 10000) */
1721
+ maxConnections?: number;
1722
+ /** Server timeout in ms (default: 120000 = 2 min) */
1723
+ serverTimeout?: number;
1724
+ /** Keep-alive timeout in ms (default: 5000) */
1725
+ keepAliveTimeout?: number;
1726
+ /** Headers timeout in ms (default: 60000) */
1727
+ headersTimeout?: number;
1728
+ /** Enable connection rate limiting (default: true) */
1729
+ rateLimitingEnabled?: boolean;
1730
+ /** Maximum new connections per second (default: 100) */
1731
+ maxConnectionsPerSecond?: number;
1732
+ /** Maximum pending connections (default: 1000) */
1733
+ maxPendingConnections?: number;
1734
+ /** Enable worker pool for CPU-bound operations (default: false) */
1735
+ workerPoolEnabled?: boolean;
1736
+ /** Worker pool configuration */
1737
+ workerPoolConfig?: Partial<WorkerPoolConfig>;
1738
+ /** Default timeout for Write Concern acknowledgments in ms (default: 5000) */
1739
+ writeAckTimeout?: number;
1740
+ /** Enable replication to backup nodes (default: true when cluster has peers) */
1741
+ replicationEnabled?: boolean;
1742
+ /** Default consistency level for replication (default: EVENTUAL) */
1743
+ defaultConsistency?: ConsistencyLevel;
1744
+ /** Replication configuration */
1745
+ replicationConfig?: Partial<ReplicationConfig>;
1746
+ }
1747
+ declare class ServerCoordinator {
1748
+ private httpServer;
1749
+ private metricsServer?;
1750
+ private metricsService;
1751
+ private wss;
1752
+ private clients;
1753
+ private interceptors;
1754
+ private maps;
1755
+ private hlc;
1756
+ private storage?;
1757
+ private jwtSecret;
1758
+ private queryRegistry;
1759
+ private cluster;
1760
+ private partitionService;
1761
+ private replicationPipeline?;
1762
+ private lockManager;
1763
+ private topicManager;
1764
+ private securityManager;
1765
+ private systemManager;
1766
+ private pendingClusterQueries;
1767
+ private gcInterval?;
1768
+ private heartbeatCheckInterval?;
1769
+ private gcReports;
1770
+ private mapLoadingPromises;
1771
+ private pendingBatchOperations;
1772
+ private eventExecutor;
1773
+ private backpressure;
1774
+ private writeCoalescingEnabled;
1775
+ private writeCoalescingOptions;
1776
+ private rateLimiter;
1777
+ private rateLimitingEnabled;
1778
+ private workerPool?;
1779
+ private merkleWorker?;
1780
+ private crdtMergeWorker?;
1781
+ private serializationWorker?;
1782
+ private eventPayloadPool;
1783
+ private taskletScheduler;
1784
+ private writeAckManager;
1785
+ private _actualPort;
1786
+ private _actualClusterPort;
1787
+ private _readyPromise;
1788
+ private _readyResolve;
1789
+ constructor(config: ServerCoordinatorConfig);
1790
+ /** Wait for server to be fully ready (ports assigned) */
1791
+ ready(): Promise<void>;
1792
+ /**
1793
+ * Wait for all pending batch operations to complete.
1794
+ * Useful for tests that need to verify state after OP_BATCH.
1795
+ */
1796
+ waitForPendingBatches(): Promise<void>;
1797
+ /** Get the actual port the server is listening on */
1798
+ get port(): number;
1799
+ /** Get the actual cluster port */
1800
+ get clusterPort(): number;
1801
+ /** Get event executor metrics for monitoring */
1802
+ getEventExecutorMetrics(): StripeMetrics[];
1803
+ /** Get total event executor metrics across all stripes */
1804
+ getEventExecutorTotalMetrics(): QueueMetrics;
1805
+ /** Get connection rate limiter stats for monitoring */
1806
+ getRateLimiterStats(): RateLimiterStats;
1807
+ /** Get worker pool stats for monitoring */
1808
+ getWorkerPoolStats(): WorkerPoolStats | null;
1809
+ /** Check if worker pool is enabled */
1810
+ get workerPoolEnabled(): boolean;
1811
+ /** Get MerkleWorker for external use (null if worker pool disabled) */
1812
+ getMerkleWorker(): MerkleWorker | null;
1813
+ /** Get CRDTMergeWorker for external use (null if worker pool disabled) */
1814
+ getCRDTMergeWorker(): CRDTMergeWorker | null;
1815
+ /** Get SerializationWorker for external use (null if worker pool disabled) */
1816
+ getSerializationWorker(): SerializationWorker | null;
1817
+ /** Get memory pool stats for monitoring GC pressure reduction */
1818
+ getMemoryPoolStats(): {
1819
+ eventPayloadPool: ObjectPoolStats;
1820
+ };
1821
+ /** Get tasklet scheduler stats for monitoring cooperative multitasking */
1822
+ getTaskletSchedulerStats(): TaskletSchedulerStats;
1823
+ /** Get tasklet scheduler for scheduling long-running operations */
1824
+ getTaskletScheduler(): TaskletScheduler;
1825
+ shutdown(): Promise<void>;
1826
+ private handleConnection;
1827
+ private handleMessage;
1828
+ private updateClientHlc;
1829
+ /**
1830
+ * Broadcast partition map to all connected and authenticated clients.
1831
+ * Called when partition topology changes (node join/leave/failover).
1832
+ */
1833
+ private broadcastPartitionMap;
1834
+ private broadcast;
1835
+ /**
1836
+ * === OPTIMIZATION 2 & 3: Batched Broadcast with Serialization Caching ===
1837
+ * Groups clients by their permission roles and serializes once per group.
1838
+ * Also batches multiple events into a single SERVER_BATCH_EVENT message.
1839
+ * === OPTIMIZATION 4: Subscription-based Routing ===
1840
+ * Only sends events to clients with active subscriptions for affected maps.
1841
+ */
1842
+ private broadcastBatch;
1843
+ /**
1844
+ * Helper method to get role signature for a client (for caching key)
1845
+ */
1846
+ private getClientRoleSignature;
1847
+ /**
1848
+ * === BACKPRESSURE: Synchronous Broadcast ===
1849
+ * Same as broadcastBatch but waits for all sends to complete.
1850
+ * Used when backpressure forces sync processing to drain the pipeline.
1851
+ */
1852
+ private broadcastBatchSync;
1853
+ private setupClusterListeners;
1854
+ private executeLocalQuery;
1855
+ private finalizeClusterQuery;
1856
+ /**
1857
+ * Core operation application logic shared between processLocalOp and processLocalOpForBatch.
1858
+ * Handles map merge, storage persistence, query evaluation, and event generation.
1859
+ *
1860
+ * @returns Event payload for broadcasting (or null if operation failed)
1861
+ */
1862
+ private applyOpToMap;
1863
+ /**
1864
+ * Broadcast event to cluster members (excluding self).
1865
+ */
1866
+ private broadcastToCluster;
1867
+ /**
1868
+ * Apply replicated operation from another node (callback for ReplicationPipeline)
1869
+ * This is called when we receive a replicated operation as a backup node
1870
+ */
1871
+ private applyReplicatedOperation;
1872
+ /**
1873
+ * Build OpContext for interceptors.
1874
+ */
1875
+ private buildOpContext;
1876
+ /**
1877
+ * Run onBeforeOp interceptors. Returns modified op or null if dropped.
1878
+ */
1879
+ private runBeforeInterceptors;
1880
+ /**
1881
+ * Run onAfterOp interceptors (fire-and-forget).
1882
+ */
1883
+ private runAfterInterceptors;
1884
+ private handleLockGranted;
1885
+ private processLocalOp;
1886
+ /**
1887
+ * === OPTIMIZATION 1: Async Batch Processing with Backpressure ===
1888
+ * Processes validated operations asynchronously after ACK has been sent.
1889
+ * Uses BackpressureRegulator to periodically force sync processing and
1890
+ * prevent unbounded accumulation of async work.
1891
+ */
1892
+ private processBatchAsync;
1893
+ /**
1894
+ * === BACKPRESSURE: Synchronous Batch Processing ===
1895
+ * Processes operations synchronously, waiting for broadcast completion.
1896
+ * Used when backpressure forces sync to drain the pipeline.
1897
+ */
1898
+ private processBatchSync;
1899
+ /**
1900
+ * Forward operation to owner node and wait for completion.
1901
+ * Used in sync processing mode.
1902
+ */
1903
+ private forwardOpAndWait;
1904
+ /**
1905
+ * Process a single operation for batch processing.
1906
+ * Uses shared applyOpToMap but collects events instead of broadcasting immediately.
1907
+ */
1908
+ private processLocalOpForBatch;
1909
+ private handleClusterEvent;
1910
+ getMap(name: string, typeHint?: 'LWW' | 'OR'): LWWMap<string, any> | ORMap<string, any>;
1911
+ /**
1912
+ * Returns map after ensuring it's fully loaded from storage.
1913
+ * Use this for queries to avoid returning empty results during initial load.
1914
+ */
1915
+ getMapAsync(name: string, typeHint?: 'LWW' | 'OR'): Promise<LWWMap<string, any> | ORMap<string, any>>;
1916
+ private loadMapFromStorage;
1917
+ private startGarbageCollection;
1918
+ /**
1919
+ * Starts the periodic check for dead clients (those that haven't sent PING).
1920
+ */
1921
+ private startHeartbeatCheck;
1922
+ /**
1923
+ * Handles incoming PING message from client.
1924
+ * Responds with PONG immediately.
1925
+ */
1926
+ private handlePing;
1927
+ /**
1928
+ * Checks if a client is still alive based on heartbeat.
1929
+ */
1930
+ isClientAlive(clientId: string): boolean;
1931
+ /**
1932
+ * Returns how long the client has been idle (no PING received).
1933
+ */
1934
+ getClientIdleTime(clientId: string): number;
1935
+ /**
1936
+ * Evicts clients that haven't sent a PING within the timeout period.
1937
+ */
1938
+ private evictDeadClients;
1939
+ private reportLocalHlc;
1940
+ private handleGcReport;
1941
+ private performGarbageCollection;
1942
+ private buildTLSOptions;
1943
+ /**
1944
+ * Get effective Write Concern level for an operation.
1945
+ * Per-op writeConcern overrides batch-level.
1946
+ */
1947
+ private getEffectiveWriteConcern;
1948
+ /**
1949
+ * Convert string WriteConcern value to enum.
1950
+ */
1951
+ private stringToWriteConcern;
1952
+ /**
1953
+ * Process batch with Write Concern tracking.
1954
+ * Notifies WriteAckManager at each stage of processing.
1955
+ */
1956
+ private processBatchAsyncWithWriteConcern;
1957
+ /**
1958
+ * Synchronous batch processing with Write Concern.
1959
+ */
1960
+ private processBatchSyncWithWriteConcern;
1961
+ /**
1962
+ * Process a single operation with Write Concern level notifications.
1963
+ */
1964
+ private processLocalOpWithWriteConcern;
1965
+ /**
1966
+ * Persist operation synchronously (blocking).
1967
+ * Used for PERSISTED Write Concern.
1968
+ */
1969
+ private persistOpSync;
1970
+ /**
1971
+ * Persist operation asynchronously (fire-and-forget).
1972
+ * Used for non-PERSISTED Write Concern levels.
1973
+ */
1974
+ private persistOpAsync;
1975
+ }
1976
+
1977
+ interface PostgresAdapterOptions {
1978
+ tableName?: string;
1979
+ }
1980
+ declare class PostgresAdapter implements IServerStorage {
1981
+ private pool;
1982
+ private tableName;
1983
+ constructor(configOrPool: PoolConfig | Pool, options?: PostgresAdapterOptions);
1984
+ initialize(): Promise<void>;
1985
+ close(): Promise<void>;
1986
+ load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
1987
+ loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
1988
+ loadAllKeys(mapName: string): Promise<string[]>;
1989
+ store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
1990
+ storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
1991
+ delete(mapName: string, key: string): Promise<void>;
1992
+ deleteAll(mapName: string, keys: string[]): Promise<void>;
1993
+ private mapRowToRecord;
1994
+ private isORMapValue;
1995
+ }
1996
+
1997
+ /**
1998
+ * In-memory implementation of IServerStorage.
1999
+ * Useful for development, testing, and demos without requiring a database.
2000
+ *
2001
+ * Note: Data is lost when the server restarts.
2002
+ */
2003
+ declare class MemoryServerAdapter implements IServerStorage {
2004
+ private storage;
2005
+ initialize(): Promise<void>;
2006
+ close(): Promise<void>;
2007
+ private getMap;
2008
+ load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
2009
+ loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
2010
+ loadAllKeys(mapName: string): Promise<string[]>;
2011
+ store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
2012
+ storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
2013
+ delete(mapName: string, key: string): Promise<void>;
2014
+ deleteAll(mapName: string, keys: string[]): Promise<void>;
2015
+ }
2016
+
2017
+ declare class SecurityManager {
2018
+ private policies;
2019
+ constructor(policies?: PermissionPolicy[]);
2020
+ addPolicy(policy: PermissionPolicy): void;
2021
+ checkPermission(principal: Principal, mapName: string, action: PermissionType): boolean;
2022
+ filterObject(object: any, principal: Principal, mapName: string): any;
2023
+ private hasRole;
2024
+ private matchesMap;
2025
+ }
2026
+
2027
+ declare const logger: pino.Logger<never, boolean>;
2028
+ type Logger = typeof logger;
2029
+
2030
+ /**
2031
+ * ConnectionRateLimiter - Rate limiter for incoming WebSocket connections.
2032
+ *
2033
+ * Implements connection rate limiting to prevent connection storms and
2034
+ * protect the server from being overwhelmed during high load scenarios.
2035
+ *
2036
+ * Features:
2037
+ * - Limits connections per second to prevent TCP backlog exhaustion
2038
+ * - Tracks pending connections (in-progress handshakes)
2039
+ * - Provides graceful rejection when limits are exceeded
2040
+ * - Auto-resets counters after cooldown period
2041
+ */
2042
+ interface RateLimiterConfig {
2043
+ /** Maximum new connections allowed per second (default: 100) */
2044
+ maxConnectionsPerSecond: number;
2045
+ /** Maximum pending connections waiting for handshake (default: 1000) */
2046
+ maxPendingConnections: number;
2047
+ /** Cooldown period in ms after which counters reset (default: 1000) */
2048
+ cooldownMs: number;
2049
+ }
2050
+ interface RateLimiterStats {
2051
+ /** Current connections per second rate */
2052
+ connectionsPerSecond: number;
2053
+ /** Number of connections currently pending (handshake in progress) */
2054
+ pendingConnections: number;
2055
+ /** Total connections established since start */
2056
+ totalConnections: number;
2057
+ /** Total connections rejected due to rate limiting */
2058
+ totalRejected: number;
2059
+ }
2060
+ declare class ConnectionRateLimiter {
2061
+ private config;
2062
+ /** Connection attempts in current window */
2063
+ private connectionCount;
2064
+ /** Timestamp when current window started */
2065
+ private windowStart;
2066
+ /** Currently pending connections (handshake in progress) */
2067
+ private pendingCount;
2068
+ /** Total connections established since start */
2069
+ private totalConnections;
2070
+ /** Total connections rejected since start */
2071
+ private totalRejected;
2072
+ constructor(config?: Partial<RateLimiterConfig>);
2073
+ /**
2074
+ * Check if a new connection should be accepted.
2075
+ * @returns true if the connection should be accepted, false if it should be rejected
2076
+ */
2077
+ shouldAccept(): boolean;
2078
+ /**
2079
+ * Register a connection attempt.
2080
+ * Call this when a new connection is initiated (before handshake completes).
2081
+ */
2082
+ onConnectionAttempt(): void;
2083
+ /**
2084
+ * Register that a connection has been established (handshake complete).
2085
+ * Call this when the connection is fully established and authenticated.
2086
+ */
2087
+ onConnectionEstablished(): void;
2088
+ /**
2089
+ * Register that a connection has been closed.
2090
+ * Call this when a pending connection is closed before completing handshake.
2091
+ */
2092
+ onConnectionClosed(): void;
2093
+ /**
2094
+ * Register that a connection was rejected.
2095
+ * Call this when shouldAccept() returns false and the connection is rejected.
2096
+ */
2097
+ onConnectionRejected(): void;
2098
+ /**
2099
+ * Decrease pending count when a connection times out or fails.
2100
+ * Call this when a pending connection fails to complete handshake.
2101
+ */
2102
+ onPendingConnectionFailed(): void;
2103
+ /**
2104
+ * Get current rate limiter statistics.
2105
+ */
2106
+ getStats(): RateLimiterStats;
2107
+ /**
2108
+ * Reset the rate limiter state.
2109
+ * Useful for testing or when recovering from errors.
2110
+ */
2111
+ reset(): void;
2112
+ /**
2113
+ * Update configuration at runtime.
2114
+ */
2115
+ updateConfig(config: Partial<RateLimiterConfig>): void;
2116
+ /**
2117
+ * Check if window has expired and reset if needed.
2118
+ */
2119
+ private maybeResetWindow;
2120
+ }
2121
+
2122
+ declare class TimestampInterceptor implements IInterceptor {
2123
+ name: string;
2124
+ onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp>;
2125
+ }
2126
+
2127
+ interface RateLimitConfig {
2128
+ windowMs: number;
2129
+ maxOps: number;
2130
+ }
2131
+ declare class RateLimitInterceptor implements IInterceptor {
2132
+ name: string;
2133
+ private limits;
2134
+ private config;
2135
+ constructor(config?: RateLimitConfig);
2136
+ onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
2137
+ onDisconnect(context: any): Promise<void>;
2138
+ }
2139
+
2140
+ /**
2141
+ * Native Module Statistics
2142
+ *
2143
+ * Provides information about available native optimizations.
2144
+ *
2145
+ * Phase 3.05: Integration
2146
+ */
2147
+
2148
+ /**
2149
+ * Native module availability status
2150
+ */
2151
+ interface NativeModuleStatus {
2152
+ /** Native xxHash64 is available and being used */
2153
+ nativeHash: boolean;
2154
+ /** SharedArrayBuffer is available */
2155
+ sharedArrayBuffer: boolean;
2156
+ }
2157
+ /**
2158
+ * Comprehensive native statistics
2159
+ */
2160
+ interface NativeStats {
2161
+ /** Module availability status */
2162
+ modules: NativeModuleStatus;
2163
+ /** Shared memory statistics (if enabled) */
2164
+ sharedMemory: SharedMemoryStats | null;
2165
+ /** Summary of what's being used */
2166
+ summary: string;
2167
+ }
2168
+ /**
2169
+ * Check which native modules are available.
2170
+ */
2171
+ declare function getNativeModuleStatus(): NativeModuleStatus;
2172
+ /**
2173
+ * Get native statistics including shared memory.
2174
+ *
2175
+ * @param sharedMemoryManager - Optional SharedMemoryManager instance
2176
+ */
2177
+ declare function getNativeStats(sharedMemoryManager?: SharedMemoryManager): NativeStats;
2178
+ /**
2179
+ * Log native module status to console.
2180
+ */
2181
+ declare function logNativeStatus(): void;
2182
+
2183
+ /**
2184
+ * FailureDetector - Phi Accrual Failure Detector
2185
+ *
2186
+ * Implements the Phi Accrual Failure Detection algorithm for distributed systems.
2187
+ * Based on the paper: "The φ Accrual Failure Detector" by Hayashibara et al.
2188
+ *
2189
+ * The detector provides a suspicion level (phi) rather than binary alive/dead status,
2190
+ * allowing the application to make decisions based on configurable thresholds.
2191
+ *
2192
+ * Hazelcast equivalent: com.hazelcast.internal.cluster.fd.PhiAccrualFailureDetector
2193
+ */
2194
+
2195
+ interface FailureDetectorConfig {
2196
+ /** Interval between heartbeat checks (ms). Default: 1000 */
2197
+ heartbeatIntervalMs: number;
2198
+ /** Time after which a node is suspected if no heartbeat received (ms). Default: 5000 */
2199
+ suspicionTimeoutMs: number;
2200
+ /** Time after suspicion before confirming failure (ms). Default: 10000 */
2201
+ confirmationTimeoutMs: number;
2202
+ /** Phi threshold above which a node is considered suspected. Default: 8 */
2203
+ phiThreshold: number;
2204
+ /** Minimum samples required for accurate phi calculation. Default: 10 */
2205
+ minSamples: number;
2206
+ /** Maximum samples to keep in history. Default: 100 */
2207
+ maxSamples: number;
2208
+ /** Initial heartbeat interval estimate (ms). Default: 1000 */
2209
+ initialHeartbeatIntervalMs: number;
2210
+ }
2211
+ declare class FailureDetector extends EventEmitter {
2212
+ private config;
2213
+ private nodeStates;
2214
+ private monitoringNodes;
2215
+ private checkTimer?;
2216
+ private confirmationTimers;
2217
+ private started;
2218
+ constructor(config?: Partial<FailureDetectorConfig>);
2219
+ /**
2220
+ * Start the failure detector monitoring loop.
2221
+ */
2222
+ start(): void;
2223
+ /**
2224
+ * Stop the failure detector and clean up.
2225
+ */
2226
+ stop(): void;
2227
+ /**
2228
+ * Start monitoring a node.
2229
+ */
2230
+ startMonitoring(nodeId: string): void;
2231
+ /**
2232
+ * Stop monitoring a node.
2233
+ */
2234
+ stopMonitoring(nodeId: string): void;
2235
+ /**
2236
+ * Record a heartbeat from a node.
2237
+ * This updates the node's state and clears any suspicion.
2238
+ */
2239
+ recordHeartbeat(nodeId: string): void;
2240
+ /**
2241
+ * Check all monitored nodes for failure.
2242
+ */
2243
+ private checkAllNodes;
2244
+ /**
2245
+ * Schedule failure confirmation after suspicion timeout.
2246
+ */
2247
+ private scheduleConfirmation;
2248
+ /**
2249
+ * Confirm node failure after confirmation timeout.
2250
+ */
2251
+ private confirmFailure;
2252
+ /**
2253
+ * Calculate the phi value for a node using the Phi Accrual algorithm.
2254
+ *
2255
+ * Phi = -log10(P_later(t_now - t_last))
2256
+ *
2257
+ * where P_later is the probability that a heartbeat will arrive later than expected.
2258
+ */
2259
+ calculatePhi(nodeId: string): number;
2260
+ /**
2261
+ * Calculate mean of an array of numbers.
2262
+ */
2263
+ private calculateMean;
2264
+ /**
2265
+ * Calculate variance of an array of numbers.
2266
+ */
2267
+ private calculateVariance;
2268
+ /**
2269
+ * Get list of currently suspected nodes.
2270
+ */
2271
+ getSuspectedNodes(): string[];
2272
+ /**
2273
+ * Get list of confirmed failed nodes.
2274
+ */
2275
+ getConfirmedFailedNodes(): string[];
2276
+ /**
2277
+ * Check if a specific node is suspected.
2278
+ */
2279
+ isSuspected(nodeId: string): boolean;
2280
+ /**
2281
+ * Check if a specific node's failure is confirmed.
2282
+ */
2283
+ isConfirmedFailed(nodeId: string): boolean;
2284
+ /**
2285
+ * Get the current phi value for a node.
2286
+ */
2287
+ getPhi(nodeId: string): number;
2288
+ /**
2289
+ * Get all monitored nodes.
2290
+ */
2291
+ getMonitoredNodes(): string[];
2292
+ /**
2293
+ * Get metrics for monitoring.
2294
+ */
2295
+ getMetrics(): {
2296
+ monitoredNodes: number;
2297
+ suspectedNodes: number;
2298
+ confirmedFailedNodes: number;
2299
+ };
2300
+ }
2301
+
2302
+ interface ClusterConfig {
2303
+ nodeId: string;
2304
+ host: string;
2305
+ port: number;
2306
+ peers: string[];
2307
+ discovery?: 'manual' | 'kubernetes';
2308
+ serviceName?: string;
2309
+ discoveryInterval?: number;
2310
+ tls?: ClusterTLSConfig;
2311
+ /** Heartbeat interval in milliseconds. Default: 1000 */
2312
+ heartbeatIntervalMs?: number;
2313
+ /** Failure detection configuration */
2314
+ failureDetection?: Partial<FailureDetectorConfig>;
2315
+ }
2316
+ interface ClusterMember {
2317
+ nodeId: string;
2318
+ host: string;
2319
+ port: number;
2320
+ socket: WebSocket;
2321
+ isSelf: boolean;
2322
+ }
2323
+ interface ClusterMessage {
2324
+ type: 'HELLO' | 'OP_FORWARD' | 'PARTITION_UPDATE' | 'HEARTBEAT' | 'CLUSTER_EVENT' | 'CLUSTER_QUERY_EXEC' | 'CLUSTER_QUERY_RESP' | 'CLUSTER_GC_REPORT' | 'CLUSTER_GC_COMMIT' | 'CLUSTER_LOCK_REQ' | 'CLUSTER_LOCK_RELEASE' | 'CLUSTER_LOCK_GRANTED' | 'CLUSTER_LOCK_RELEASED' | 'CLUSTER_CLIENT_DISCONNECTED' | 'CLUSTER_TOPIC_PUB';
2325
+ senderId: string;
2326
+ payload: any;
2327
+ }
2328
+ declare class ClusterManager extends EventEmitter {
2329
+ readonly config: ClusterConfig;
2330
+ private server?;
2331
+ private members;
2332
+ private pendingConnections;
2333
+ private reconnectIntervals;
2334
+ private discoveryTimer?;
2335
+ private heartbeatTimer?;
2336
+ private failureDetector;
2337
+ constructor(config: ClusterConfig);
2338
+ /**
2339
+ * Get the failure detector instance.
2340
+ */
2341
+ getFailureDetector(): FailureDetector;
2342
+ private _actualPort;
2343
+ /** Get the actual port the cluster is listening on */
2344
+ get port(): number;
2345
+ start(): Promise<number>;
2346
+ /** Called when server is ready - registers self and initiates peer connections */
2347
+ private onServerReady;
2348
+ stop(): void;
2349
+ /**
2350
+ * Start sending heartbeats to all peers.
2351
+ */
2352
+ private startHeartbeat;
2353
+ /**
2354
+ * Stop sending heartbeats.
2355
+ */
2356
+ private stopHeartbeat;
2357
+ /**
2358
+ * Send heartbeat to all connected peers.
2359
+ */
2360
+ private sendHeartbeatToAll;
2361
+ /**
2362
+ * Handle incoming heartbeat from a peer.
2363
+ */
2364
+ private handleHeartbeat;
2365
+ /**
2366
+ * Handle confirmed node failure.
2367
+ */
2368
+ private handleNodeFailure;
2369
+ private connectToPeers;
2370
+ private startDiscovery;
2371
+ private scheduleReconnect;
2372
+ private connectToPeerWithBackoff;
2373
+ private connectToPeer;
2374
+ private _connectToPeerInternal;
2375
+ private handleSocket;
2376
+ send(nodeId: string, type: ClusterMessage['type'], payload: any): void;
2377
+ sendToNode(nodeId: string, message: any): void;
2378
+ getMembers(): string[];
2379
+ isLocal(nodeId: string): boolean;
2380
+ private buildClusterTLSOptions;
2381
+ }
2382
+
2383
+ /**
2384
+ * MigrationManager - Manages gradual partition rebalancing
2385
+ *
2386
+ * Phase 4 Task 03: Parallel Partition Sync
2387
+ *
2388
+ * Features:
2389
+ * - Gradual rebalancing with configurable batch size
2390
+ * - State machine for migration lifecycle
2391
+ * - Backpressure via chunk acknowledgments
2392
+ * - Retry logic for failed migrations
2393
+ * - Metrics and observability
2394
+ */
2395
+
2396
+ declare class MigrationManager extends EventEmitter {
2397
+ private readonly config;
2398
+ private readonly clusterManager;
2399
+ private readonly partitionService;
2400
+ private activeMigrations;
2401
+ private migrationQueue;
2402
+ private incomingMigrations;
2403
+ private pendingChunkAcks;
2404
+ private pendingVerifications;
2405
+ private metrics;
2406
+ private batchTimer;
2407
+ private dataCollector;
2408
+ private dataStorer;
2409
+ constructor(clusterManager: ClusterManager, partitionService: PartitionService, config?: Partial<MigrationConfig>);
2410
+ /**
2411
+ * Set the data collector callback
2412
+ * Called to collect all records for a partition before migration
2413
+ */
2414
+ setDataCollector(collector: (partitionId: number) => Promise<Uint8Array[]>): void;
2415
+ /**
2416
+ * Set the data storer callback
2417
+ * Called to store received records after successful migration
2418
+ */
2419
+ setDataStorer(storer: (partitionId: number, data: Uint8Array[]) => Promise<void>): void;
2420
+ /**
2421
+ * Plan migration for topology change
2422
+ */
2423
+ planMigration(oldDistribution: Map<number, PartitionDistribution>, newDistribution: Map<number, PartitionDistribution>): void;
2424
+ /**
2425
+ * Start batch processing timer
2426
+ */
2427
+ private startBatchProcessing;
2428
+ /**
2429
+ * Stop batch processing
2430
+ */
2431
+ private stopBatchProcessing;
2432
+ /**
2433
+ * Start next batch of migrations
2434
+ */
2435
+ startNextBatch(): Promise<void>;
2436
+ /**
2437
+ * Start migration for a single partition
2438
+ */
2439
+ private startPartitionMigration;
2440
+ /**
2441
+ * Split records into chunks
2442
+ */
2443
+ private chunkify;
2444
+ /**
2445
+ * Calculate checksum for a chunk using native xxhash
2446
+ */
2447
+ private calculateChecksum;
2448
+ /**
2449
+ * Calculate checksum for all partition records using streaming xxhash
2450
+ */
2451
+ private calculatePartitionChecksum;
2452
+ /**
2453
+ * Wait for chunk acknowledgment
2454
+ */
2455
+ private waitForChunkAck;
2456
+ /**
2457
+ * Wait for migration verification
2458
+ */
2459
+ private waitForVerification;
2460
+ /**
2461
+ * Handle successful migration completion
2462
+ */
2463
+ private onMigrationComplete;
2464
+ /**
2465
+ * Handle migration failure
2466
+ */
2467
+ private onMigrationFailed;
2468
+ /**
2469
+ * Handle MIGRATION_START message
2470
+ */
2471
+ private handleMigrationStart;
2472
+ /**
2473
+ * Handle MIGRATION_CHUNK message
2474
+ */
2475
+ private handleMigrationChunk;
2476
+ /**
2477
+ * Handle MIGRATION_COMPLETE message
2478
+ */
2479
+ private handleMigrationComplete;
2480
+ /**
2481
+ * Handle MIGRATION_CHUNK_ACK message
2482
+ */
2483
+ private handleMigrationChunkAck;
2484
+ /**
2485
+ * Handle MIGRATION_VERIFY message
2486
+ */
2487
+ private handleMigrationVerify;
2488
+ /**
2489
+ * Reassemble chunks into continuous data
2490
+ */
2491
+ private reassemble;
2492
+ /**
2493
+ * Deserialize records from chunk data
2494
+ */
2495
+ private deserializeRecords;
2496
+ /**
2497
+ * Setup cluster message handlers
2498
+ */
2499
+ private setupMessageHandlers;
2500
+ /**
2501
+ * Check if a partition is currently migrating
2502
+ */
2503
+ isActive(partitionId: number): boolean;
2504
+ /**
2505
+ * Get migration status
2506
+ */
2507
+ getStatus(): MigrationStatus;
2508
+ /**
2509
+ * Get migration metrics
2510
+ */
2511
+ getMetrics(): MigrationMetrics;
2512
+ /**
2513
+ * Cancel all active and queued migrations
2514
+ */
2515
+ cancelAll(): Promise<void>;
2516
+ /**
2517
+ * Cleanup resources (sync version for backwards compatibility)
2518
+ */
2519
+ close(): void;
2520
+ /**
2521
+ * Async cleanup - waits for cancellation to complete
2522
+ */
2523
+ closeAsync(): Promise<void>;
2524
+ }
2525
+
2526
+ interface PartitionDistribution {
2527
+ owner: string;
2528
+ backups: string[];
2529
+ }
2530
+ interface PartitionServiceEvents {
2531
+ 'rebalanced': (map: PartitionMap, changes: PartitionChange[]) => void;
2532
+ 'partitionMoved': (info: {
2533
+ partitionId: number;
2534
+ previousOwner: string;
2535
+ newOwner: string;
2536
+ version: number;
2537
+ }) => void;
2538
+ }
2539
+ interface PartitionServiceConfig {
2540
+ /** Enable gradual rebalancing (default: false for backward compatibility) */
2541
+ gradualRebalancing: boolean;
2542
+ /** Migration configuration */
2543
+ migration: Partial<MigrationConfig>;
2544
+ }
2545
+ declare class PartitionService extends EventEmitter {
2546
+ private cluster;
2547
+ private partitions;
2548
+ private readonly PARTITION_COUNT;
2549
+ private readonly BACKUP_COUNT;
2550
+ private mapVersion;
2551
+ private lastRebalanceTime;
2552
+ private config;
2553
+ private migrationManager;
2554
+ constructor(cluster: ClusterManager, config?: Partial<PartitionServiceConfig>);
2555
+ /**
2556
+ * Handle membership change
2557
+ */
2558
+ private onMembershipChange;
2559
+ getPartitionId(key: string): number;
2560
+ getDistribution(key: string): PartitionDistribution;
2561
+ getOwner(key: string): string;
2562
+ isLocalOwner(key: string): boolean;
2563
+ isLocalBackup(key: string): boolean;
2564
+ isRelated(key: string): boolean;
2565
+ /**
2566
+ * Get current partition map version
2567
+ */
2568
+ getMapVersion(): number;
2569
+ /**
2570
+ * Generate full PartitionMap for client consumption
2571
+ */
2572
+ getPartitionMap(): PartitionMap;
2573
+ /**
2574
+ * Get partition info by ID
2575
+ */
2576
+ getPartitionInfo(partitionId: number): PartitionInfo | null;
2577
+ /**
2578
+ * Get owner node for a partition ID
2579
+ */
2580
+ getPartitionOwner(partitionId: number): string | null;
2581
+ private rebalance;
2582
+ /**
2583
+ * Perform gradual rebalancing using MigrationManager
2584
+ */
2585
+ private rebalanceGradual;
2586
+ /**
2587
+ * Set partition owner (called after migration completes)
2588
+ */
2589
+ setOwner(partitionId: number, nodeId: string): void;
2590
+ /**
2591
+ * Get backups for a partition
2592
+ */
2593
+ getBackups(partitionId: number): string[];
2594
+ /**
2595
+ * Get migration status
2596
+ */
2597
+ getMigrationStatus(): MigrationStatus | null;
2598
+ /**
2599
+ * Check if partition is currently migrating
2600
+ */
2601
+ isMigrating(partitionId: number): boolean;
2602
+ /**
2603
+ * Check if any partition is currently migrating
2604
+ */
2605
+ isRebalancing(): boolean;
2606
+ /**
2607
+ * Get MigrationManager for configuration
2608
+ */
2609
+ getMigrationManager(): MigrationManager | null;
2610
+ /**
2611
+ * Cancel all migrations
2612
+ */
2613
+ cancelMigrations(): Promise<void>;
2614
+ }
2615
+
2616
+ /**
2617
+ * LagTracker - Monitors replication lag across cluster nodes
2618
+ *
2619
+ * Phase 4 Task 04: Async Replication Pipeline
2620
+ *
2621
+ * Features:
2622
+ * - Tracks replication lag per node
2623
+ * - Maintains historical lag data for percentile calculations
2624
+ * - Identifies unhealthy and laggy nodes
2625
+ * - Provides health metrics for monitoring
2626
+ */
2627
+
2628
+ interface LagInfo {
2629
+ current: number;
2630
+ history: number[];
2631
+ lastUpdate: number;
2632
+ pendingOps: number;
2633
+ }
2634
+ interface LagTrackerConfig {
2635
+ /** Number of lag samples to keep in history (default: 100) */
2636
+ historySize: number;
2637
+ /** Threshold in ms for considering a node laggy (default: 5000) */
2638
+ laggyThresholdMs: number;
2639
+ /** Threshold in ms for considering a node unhealthy (default: 30000) */
2640
+ unhealthyThresholdMs: number;
2641
+ }
2642
+ declare const DEFAULT_LAG_TRACKER_CONFIG: LagTrackerConfig;
2643
+ declare class LagTracker {
2644
+ private readonly config;
2645
+ private lagByNode;
2646
+ constructor(config?: Partial<LagTrackerConfig>);
2647
+ /**
2648
+ * Update lag measurement for a node
2649
+ */
2650
+ update(nodeId: string, lagMs: number): void;
2651
+ /**
2652
+ * Record acknowledgment from a node (lag effectively becomes 0)
2653
+ */
2654
+ recordAck(nodeId: string): void;
2655
+ /**
2656
+ * Increment pending operations counter for a node
2657
+ */
2658
+ incrementPending(nodeId: string): void;
2659
+ /**
2660
+ * Get lag statistics for a specific node
2661
+ */
2662
+ getLag(nodeId: string): ReplicationLag;
2663
+ /**
2664
+ * Get pending operations count for a node
2665
+ */
2666
+ getPendingOps(nodeId: string): number;
2667
+ /**
2668
+ * Get overall replication health status
2669
+ */
2670
+ getHealth(): ReplicationHealth;
2671
+ /**
2672
+ * Get average lag across all tracked nodes
2673
+ */
2674
+ getAverageLag(): number;
2675
+ /**
2676
+ * Check if a specific node is considered healthy
2677
+ */
2678
+ isNodeHealthy(nodeId: string): boolean;
2679
+ /**
2680
+ * Check if a specific node is considered laggy
2681
+ */
2682
+ isNodeLaggy(nodeId: string): boolean;
2683
+ /**
2684
+ * Remove a node from tracking
2685
+ */
2686
+ removeNode(nodeId: string): void;
2687
+ /**
2688
+ * Get all tracked node IDs
2689
+ */
2690
+ getTrackedNodes(): string[];
2691
+ /**
2692
+ * Get raw lag info for a node (for advanced monitoring)
2693
+ */
2694
+ getRawLagInfo(nodeId: string): LagInfo | undefined;
2695
+ /**
2696
+ * Clear all tracking data
2697
+ */
2698
+ clear(): void;
2699
+ /**
2700
+ * Export metrics in Prometheus format
2701
+ */
2702
+ toPrometheusMetrics(): string;
2703
+ }
2704
+
2705
+ /**
2706
+ * ReplicationPipeline - Manages async replication with configurable consistency levels
2707
+ *
2708
+ * Phase 4 Task 04: Async Replication Pipeline
2709
+ *
2710
+ * Features:
2711
+ * - Three consistency levels: STRONG, QUORUM, EVENTUAL
2712
+ * - Async replication queue for high throughput
2713
+ * - Backpressure handling with queue limits
2714
+ * - Retry logic for failed replications
2715
+ * - Integration with LagTracker for monitoring
2716
+ * - Pluggable operation applier for storage integration
2717
+ */
2718
+
2719
+ /**
2720
+ * Callback to apply replicated operation to local storage
2721
+ * @param operation - The operation to apply
2722
+ * @param opId - Unique operation ID
2723
+ * @param sourceNode - Node that originated the operation
2724
+ * @returns Promise<boolean> - true if applied successfully
2725
+ */
2726
+ type OperationApplier = (operation: unknown, opId: string, sourceNode: string) => Promise<boolean>;
2727
+ declare class ReplicationPipeline extends EventEmitter {
2728
+ private readonly config;
2729
+ private readonly clusterManager;
2730
+ private readonly partitionService;
2731
+ private readonly lagTracker;
2732
+ private readonly nodeId;
2733
+ private replicationQueue;
2734
+ private pendingAcks;
2735
+ private queueProcessorTimer;
2736
+ private operationApplier;
2737
+ constructor(clusterManager: ClusterManager, partitionService: PartitionService, config?: Partial<ReplicationConfig>);
2738
+ /**
2739
+ * Set the operation applier callback
2740
+ * This is called when replicated operations are received from other nodes
2741
+ */
2742
+ setOperationApplier(applier: OperationApplier): void;
2743
+ /**
2744
+ * Replicate operation to backup nodes
2745
+ */
2746
+ replicate(operation: unknown, opId: string, key: string, options?: {
2747
+ consistency?: ConsistencyLevel;
2748
+ timeout?: number;
2749
+ }): Promise<ReplicationResult>;
2750
+ /**
2751
+ * STRONG: Wait for all replicas to acknowledge
2752
+ */
2753
+ private replicateStrong;
2754
+ /**
2755
+ * QUORUM: Wait for majority of replicas
2756
+ */
2757
+ private replicateQuorum;
2758
+ /**
2759
+ * EVENTUAL: Fire-and-forget with queue
2760
+ */
2761
+ private replicateEventual;
2762
+ /**
2763
+ * Add task to replication queue
2764
+ */
2765
+ private enqueue;
2766
+ /**
2767
+ * Start queue processor
2768
+ */
2769
+ private startQueueProcessor;
2770
+ /**
2771
+ * Stop queue processor
2772
+ */
2773
+ private stopQueueProcessor;
2774
+ /**
2775
+ * Process replication queue for a node
2776
+ */
2777
+ private processQueue;
2778
+ /**
2779
+ * Send replication message to a node
2780
+ */
2781
+ private sendReplication;
2782
+ /**
2783
+ * Setup cluster message handlers
2784
+ */
2785
+ private setupMessageHandlers;
2786
+ /**
2787
+ * Handle incoming replication request (on backup node)
2788
+ */
2789
+ private handleReplication;
2790
+ /**
2791
+ * Handle incoming batch replication (on backup node)
2792
+ */
2793
+ private handleReplicationBatch;
2794
+ /**
2795
+ * Handle replication acknowledgment (on owner node)
2796
+ */
2797
+ private handleReplicationAck;
2798
+ /**
2799
+ * Handle batch acknowledgment (on owner node)
2800
+ */
2801
+ private handleReplicationBatchAck;
2802
+ /**
2803
+ * Get replication lag for a specific node
2804
+ */
2805
+ getLag(nodeId: string): ReplicationLag;
2806
+ /**
2807
+ * Get overall replication health
2808
+ */
2809
+ getHealth(): ReplicationHealth;
2810
+ /**
2811
+ * Get queue size for a specific node
2812
+ */
2813
+ getQueueSize(nodeId: string): number;
2814
+ /**
2815
+ * Get total pending operations across all nodes
2816
+ */
2817
+ getTotalPending(): number;
2818
+ /**
2819
+ * Check if a node is considered synced (low lag)
2820
+ */
2821
+ isSynced(nodeId: string, maxLagMs?: number): boolean;
2822
+ /**
2823
+ * Get LagTracker for advanced monitoring
2824
+ */
2825
+ getLagTracker(): LagTracker;
2826
+ /**
2827
+ * Export metrics in Prometheus format
2828
+ */
2829
+ toPrometheusMetrics(): string;
2830
+ /**
2831
+ * Cleanup resources
2832
+ */
2833
+ close(): void;
2834
+ }
2835
+
2836
+ declare class LockManager extends EventEmitter {
2837
+ private locks;
2838
+ private checkInterval;
2839
+ private static readonly MIN_TTL;
2840
+ private static readonly MAX_TTL;
2841
+ constructor();
2842
+ stop(): void;
2843
+ acquire(name: string, clientId: string, requestId: string, ttl: number): {
2844
+ granted: boolean;
2845
+ fencingToken?: number;
2846
+ error?: string;
2847
+ };
2848
+ release(name: string, clientId: string, fencingToken: number): boolean;
2849
+ handleClientDisconnect(clientId: string): void;
2850
+ private grantLock;
2851
+ private processNext;
2852
+ private cleanupExpiredLocks;
2853
+ }
2854
+
2855
+ /**
2856
+ * ClusterCoordinator - Unified cluster integration layer
2857
+ *
2858
+ * Phase 4 Task 06: System Integration
2859
+ *
2860
+ * Coordinates all cluster components:
2861
+ * - ClusterManager: P2P WebSocket mesh
2862
+ * - PartitionService: Consistent hashing & routing
2863
+ * - MigrationManager: Gradual rebalancing
2864
+ * - ReplicationPipeline: Async replication with consistency levels
2865
+ * - LagTracker: Replication health monitoring
2866
+ */
2867
+
2868
+ interface ClusterCoordinatorConfig {
2869
+ /** Cluster node configuration */
2870
+ cluster: ClusterConfig;
2871
+ /** Enable gradual partition rebalancing (default: true) */
2872
+ gradualRebalancing: boolean;
2873
+ /** Migration configuration for gradual rebalancing */
2874
+ migration: Partial<MigrationConfig>;
2875
+ /** Replication configuration */
2876
+ replication: Partial<ReplicationConfig>;
2877
+ /** Enable async replication pipeline (default: true) */
2878
+ replicationEnabled: boolean;
2879
+ /** Data collector callback for migrations */
2880
+ dataCollector?: (partitionId: number) => Promise<Uint8Array[]>;
2881
+ /** Data storer callback for incoming migrations */
2882
+ dataStorer?: (partitionId: number, data: Uint8Array[]) => Promise<void>;
2883
+ }
2884
+ declare const DEFAULT_CLUSTER_COORDINATOR_CONFIG: Omit<ClusterCoordinatorConfig, 'cluster'>;
2885
+ interface ClusterCoordinatorEvents {
2886
+ 'started': () => void;
2887
+ 'stopped': () => void;
2888
+ 'member:joined': (nodeId: string) => void;
2889
+ 'member:left': (nodeId: string) => void;
2890
+ 'partition:rebalanced': (map: PartitionMap, changes: PartitionChange[]) => void;
2891
+ 'partition:moved': (info: {
2892
+ partitionId: number;
2893
+ previousOwner: string;
2894
+ newOwner: string;
2895
+ version: number;
2896
+ }) => void;
2897
+ 'migration:started': (partitionId: number, targetNode: string) => void;
2898
+ 'migration:completed': (partitionId: number) => void;
2899
+ 'migration:failed': (partitionId: number, error: Error) => void;
2900
+ 'replication:unhealthy': (nodeId: string) => void;
2901
+ 'replication:healthy': (nodeId: string) => void;
2902
+ 'error': (error: Error) => void;
2903
+ }
2904
+ declare class ClusterCoordinator extends EventEmitter {
2905
+ private readonly config;
2906
+ private clusterManager;
2907
+ private partitionService;
2908
+ private replicationPipeline;
2909
+ private lagTracker;
2910
+ private started;
2911
+ private actualPort;
2912
+ constructor(config: ClusterCoordinatorConfig);
2913
+ /**
2914
+ * Start the cluster coordinator
2915
+ */
2916
+ start(): Promise<number>;
2917
+ /**
2918
+ * Stop the cluster coordinator
2919
+ */
2920
+ stop(): Promise<void>;
2921
+ /**
2922
+ * Get local node ID
2923
+ */
2924
+ getNodeId(): string;
2925
+ /**
2926
+ * Get cluster port
2927
+ */
2928
+ getPort(): number;
2929
+ /**
2930
+ * Get all cluster members
2931
+ */
2932
+ getMembers(): string[];
2933
+ /**
2934
+ * Check if this is the local node
2935
+ */
2936
+ isLocal(nodeId: string): boolean;
2937
+ /**
2938
+ * Check if coordinator is started
2939
+ */
2940
+ isStarted(): boolean;
2941
+ /**
2942
+ * Get current partition map
2943
+ */
2944
+ getPartitionMap(): PartitionMap;
2945
+ /**
2946
+ * Get partition map version
2947
+ */
2948
+ getPartitionMapVersion(): number;
2949
+ /**
2950
+ * Get partition ID for a key
2951
+ */
2952
+ getPartitionId(key: string): number;
2953
+ /**
2954
+ * Get owner node for a key
2955
+ */
2956
+ getOwner(key: string): string;
2957
+ /**
2958
+ * Check if this node owns the key
2959
+ */
2960
+ isLocalOwner(key: string): boolean;
2961
+ /**
2962
+ * Check if this node is a backup for the key
2963
+ */
2964
+ isLocalBackup(key: string): boolean;
2965
+ /**
2966
+ * Get backup nodes for a partition
2967
+ */
2968
+ getBackups(partitionId: number): string[];
2969
+ /**
2970
+ * Check if partition is currently migrating
2971
+ */
2972
+ isMigrating(partitionId: number): boolean;
2973
+ /**
2974
+ * Check if any rebalancing is in progress
2975
+ */
2976
+ isRebalancing(): boolean;
2977
+ /**
2978
+ * Get migration status
2979
+ */
2980
+ getMigrationStatus(): MigrationStatus | null;
2981
+ /**
2982
+ * Get migration metrics
2983
+ */
2984
+ getMigrationMetrics(): MigrationMetrics | null;
2985
+ /**
2986
+ * Cancel all active migrations
2987
+ */
2988
+ cancelMigrations(): Promise<void>;
2989
+ /**
2990
+ * Set data collector for migrations
2991
+ */
2992
+ setDataCollector(collector: (partitionId: number) => Promise<Uint8Array[]>): void;
2993
+ /**
2994
+ * Set data storer for incoming migrations
2995
+ */
2996
+ setDataStorer(storer: (partitionId: number, data: Uint8Array[]) => Promise<void>): void;
2997
+ /**
2998
+ * Replicate an operation to backup nodes
2999
+ */
3000
+ replicate(operation: unknown, opId: string, key: string, options?: {
3001
+ consistency?: ConsistencyLevel;
3002
+ timeout?: number;
3003
+ }): Promise<ReplicationResult>;
3004
+ /**
3005
+ * Get replication health status
3006
+ */
3007
+ getReplicationHealth(): ReplicationHealth;
3008
+ /**
3009
+ * Get replication lag for a specific node
3010
+ */
3011
+ getReplicationLag(nodeId: string): ReplicationLag;
3012
+ /**
3013
+ * Check if a node is healthy for replication
3014
+ */
3015
+ isNodeHealthy(nodeId: string): boolean;
3016
+ /**
3017
+ * Check if a node is laggy
3018
+ */
3019
+ isNodeLaggy(nodeId: string): boolean;
3020
+ /**
3021
+ * Send message to a specific node
3022
+ */
3023
+ send(nodeId: string, message: unknown): void;
3024
+ /**
3025
+ * Broadcast message to all nodes
3026
+ */
3027
+ broadcast(message: unknown): void;
3028
+ /**
3029
+ * Get underlying ClusterManager
3030
+ */
3031
+ getClusterManager(): ClusterManager;
3032
+ /**
3033
+ * Get underlying PartitionService
3034
+ */
3035
+ getPartitionService(): PartitionService;
3036
+ /**
3037
+ * Get underlying ReplicationPipeline
3038
+ */
3039
+ getReplicationPipeline(): ReplicationPipeline | null;
3040
+ /**
3041
+ * Get underlying LagTracker
3042
+ */
3043
+ getLagTracker(): LagTracker;
3044
+ /**
3045
+ * Get all metrics in Prometheus format
3046
+ */
3047
+ getPrometheusMetrics(): string;
3048
+ private setupEventHandlers;
331
3049
  }
332
3050
 
333
- export { type ConnectionContext, type IInterceptor, type IServerStorage, type Logger, MemoryServerAdapter, type ORMapTombstones, type ORMapValue, type OpContext, PostgresAdapter, type PostgresAdapterOptions, RateLimitInterceptor, SecurityManager, ServerCoordinator, type ServerCoordinatorConfig, type ServerOp, type StorageValue, TimestampInterceptor, logger };
3051
+ export { BufferPool, type BufferPoolConfig, type BufferPoolStats, type ClusterConfig, ClusterCoordinator, type ClusterCoordinatorConfig, type ClusterCoordinatorEvents, ClusterManager, type ClusterMember, type ClusterMessage, type CoalescingPreset, type CoalescingWriterMetrics, type CoalescingWriterOptions, type ConnectionContext, ConnectionRateLimiter, DEFAULT_CLUSTER_COORDINATOR_CONFIG, DEFAULT_LAG_TRACKER_CONFIG, FilterTasklet, ForEachTasklet, type IInterceptor, type IServerStorage, IteratorTasklet, type IteratorTaskletConfig, type LagInfo, LagTracker, type LagTrackerConfig, LockManager, type Logger, MapTasklet, MemoryServerAdapter, MigrationManager, type NativeModuleStatus, type NativeStats, type ORMapTombstones, type ORMapValue, ObjectPool, type ObjectPoolConfig, type ObjectPoolStats, type OpContext, type PartitionDistribution, PartitionService, type PartitionServiceConfig, type PartitionServiceEvents, type PooledEventPayload, type PooledMessage, type PooledRecord, type PooledTimestamp, PostgresAdapter, type PostgresAdapterOptions, type ProgressState, RateLimitInterceptor, type RateLimiterConfig, type RateLimiterStats, ReduceTasklet, ReplicationPipeline, SecurityManager, ServerCoordinator, type ServerCoordinatorConfig, type ServerOp, type StorageValue, type Tasklet, TaskletScheduler, type TaskletSchedulerConfig, type TaskletSchedulerStats, TimestampInterceptor, coalescingPresets, createEventPayloadPool, createMessagePool, createRecordPool, createTimestampPool, getCoalescingPreset, getGlobalBufferPool, getGlobalEventPayloadPool, getGlobalMessagePool, getGlobalRecordPool, getGlobalTimestampPool, getNativeModuleStatus, getNativeStats, logNativeStatus, logger, setGlobalBufferPool, setGlobalEventPayloadPool, setGlobalMessagePool, setGlobalRecordPool, setGlobalTimestampPool };