@topgunbuild/server 0.6.0 → 0.8.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.mts +874 -3
- package/dist/index.d.ts +874 -3
- package/dist/index.js +2595 -302
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2506 -222
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _topgunbuild_core from '@topgunbuild/core';
|
|
2
|
-
import { Timestamp, LWWRecord, ORMapRecord, Principal, EventJournalImpl, EventJournalConfig, JournalEvent, PermissionPolicy, ConsistencyLevel, ReplicationConfig, LWWMap, ORMap, PermissionType, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, ReplicationLag, ReplicationHealth, ReplicationResult, EntryProcessorDef, EntryProcessorResult, HLC, MergeRejection, ConflictResolverDef, MergeContext, MergeResult, IndexedLWWMap, IndexedORMap } from '@topgunbuild/core';
|
|
2
|
+
import { Timestamp, LWWRecord, ORMapRecord, Principal, EventJournalImpl, EventJournalConfig, JournalEvent, PermissionPolicy, ConsistencyLevel, ReplicationConfig, FullTextIndexConfig, LWWMap, ORMap, PermissionType, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, ReplicationLag, ReplicationHealth, ReplicationResult, ClusterReadOptions, MerkleTree, EntryProcessorDef, EntryProcessorResult, HLC, MergeRejection, ConflictResolverDef, MergeContext, MergeResult, IndexedLWWMap, IndexedORMap, SearchUpdateType, FTSSearchOptions, SearchRespPayload, SearchOptions } from '@topgunbuild/core';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
import { Pool, PoolConfig } from 'pg';
|
|
5
5
|
import pino from 'pino';
|
|
@@ -1858,6 +1858,8 @@ interface ServerCoordinatorConfig {
|
|
|
1858
1858
|
eventJournalEnabled?: boolean;
|
|
1859
1859
|
/** Event journal configuration */
|
|
1860
1860
|
eventJournalConfig?: Partial<Omit<EventJournalServiceConfig, 'pool'>>;
|
|
1861
|
+
/** Enable full-text search for specific maps */
|
|
1862
|
+
fullTextSearch?: Record<string, FullTextIndexConfig>;
|
|
1861
1863
|
}
|
|
1862
1864
|
declare class ServerCoordinator {
|
|
1863
1865
|
private httpServer;
|
|
@@ -1902,12 +1904,22 @@ declare class ServerCoordinator {
|
|
|
1902
1904
|
private conflictResolverHandler;
|
|
1903
1905
|
private eventJournalService?;
|
|
1904
1906
|
private journalSubscriptions;
|
|
1907
|
+
private partitionReassigner?;
|
|
1908
|
+
private readReplicaHandler?;
|
|
1909
|
+
private merkleTreeManager?;
|
|
1910
|
+
private repairScheduler?;
|
|
1911
|
+
private searchCoordinator;
|
|
1905
1912
|
private readonly _nodeId;
|
|
1906
1913
|
private _actualPort;
|
|
1907
1914
|
private _actualClusterPort;
|
|
1908
1915
|
private _readyPromise;
|
|
1909
1916
|
private _readyResolve;
|
|
1910
1917
|
constructor(config: ServerCoordinatorConfig);
|
|
1918
|
+
/**
|
|
1919
|
+
* Populate FTS indexes from existing map data.
|
|
1920
|
+
* Called after storage initialization.
|
|
1921
|
+
*/
|
|
1922
|
+
private backfillSearchIndexes;
|
|
1911
1923
|
/** Wait for server to be fully ready (ports assigned) */
|
|
1912
1924
|
ready(): Promise<void>;
|
|
1913
1925
|
/**
|
|
@@ -1943,6 +1955,54 @@ declare class ServerCoordinator {
|
|
|
1943
1955
|
getTaskletSchedulerStats(): TaskletSchedulerStats;
|
|
1944
1956
|
/** Get tasklet scheduler for scheduling long-running operations */
|
|
1945
1957
|
getTaskletScheduler(): TaskletScheduler;
|
|
1958
|
+
/**
|
|
1959
|
+
* Enable full-text search for a map.
|
|
1960
|
+
* Can be called at runtime to enable FTS dynamically.
|
|
1961
|
+
*
|
|
1962
|
+
* @param mapName - Name of the map to enable FTS for
|
|
1963
|
+
* @param config - FTS configuration (fields, tokenizer, bm25 options)
|
|
1964
|
+
*/
|
|
1965
|
+
enableFullTextSearch(mapName: string, config: FullTextIndexConfig): void;
|
|
1966
|
+
/**
|
|
1967
|
+
* Disable full-text search for a map.
|
|
1968
|
+
*
|
|
1969
|
+
* @param mapName - Name of the map to disable FTS for
|
|
1970
|
+
*/
|
|
1971
|
+
disableFullTextSearch(mapName: string): void;
|
|
1972
|
+
/**
|
|
1973
|
+
* Check if full-text search is enabled for a map.
|
|
1974
|
+
*
|
|
1975
|
+
* @param mapName - Name of the map to check
|
|
1976
|
+
* @returns True if FTS is enabled
|
|
1977
|
+
*/
|
|
1978
|
+
isFullTextSearchEnabled(mapName: string): boolean;
|
|
1979
|
+
/**
|
|
1980
|
+
* Get FTS index statistics for a map.
|
|
1981
|
+
*
|
|
1982
|
+
* @param mapName - Name of the map
|
|
1983
|
+
* @returns Index stats or null if FTS not enabled
|
|
1984
|
+
*/
|
|
1985
|
+
getFullTextSearchStats(mapName: string): {
|
|
1986
|
+
documentCount: number;
|
|
1987
|
+
fields: string[];
|
|
1988
|
+
} | null;
|
|
1989
|
+
/**
|
|
1990
|
+
* Phase 10.02: Graceful cluster departure
|
|
1991
|
+
*
|
|
1992
|
+
* Notifies the cluster that this node is leaving and allows time for:
|
|
1993
|
+
* 1. Pending replication to complete
|
|
1994
|
+
* 2. Other nodes to detect departure
|
|
1995
|
+
* 3. Partition reassignment to begin
|
|
1996
|
+
*/
|
|
1997
|
+
private gracefulClusterDeparture;
|
|
1998
|
+
/**
|
|
1999
|
+
* Get list of partition IDs owned by this node
|
|
2000
|
+
*/
|
|
2001
|
+
private getOwnedPartitions;
|
|
2002
|
+
/**
|
|
2003
|
+
* Wait for replication pipeline to flush pending operations
|
|
2004
|
+
*/
|
|
2005
|
+
private waitForReplicationFlush;
|
|
1946
2006
|
shutdown(): Promise<void>;
|
|
1947
2007
|
private handleConnection;
|
|
1948
2008
|
private handleMessage;
|
|
@@ -2052,6 +2112,16 @@ declare class ServerCoordinator {
|
|
|
2052
2112
|
* Use this for queries to avoid returning empty results during initial load.
|
|
2053
2113
|
*/
|
|
2054
2114
|
getMapAsync(name: string, typeHint?: 'LWW' | 'OR'): Promise<LWWMap<string, any> | ORMap<string, any>>;
|
|
2115
|
+
/**
|
|
2116
|
+
* Phase 10.04: Get local record for anti-entropy repair
|
|
2117
|
+
* Returns the LWWRecord for a key, used by RepairScheduler
|
|
2118
|
+
*/
|
|
2119
|
+
private getLocalRecord;
|
|
2120
|
+
/**
|
|
2121
|
+
* Phase 10.04: Apply repaired record from anti-entropy repair
|
|
2122
|
+
* Used by RepairScheduler to apply resolved conflicts
|
|
2123
|
+
*/
|
|
2124
|
+
private applyRepairRecord;
|
|
2055
2125
|
private loadMapFromStorage;
|
|
2056
2126
|
private startGarbageCollection;
|
|
2057
2127
|
/**
|
|
@@ -2347,6 +2417,31 @@ interface FailureDetectorConfig {
|
|
|
2347
2417
|
/** Initial heartbeat interval estimate (ms). Default: 1000 */
|
|
2348
2418
|
initialHeartbeatIntervalMs: number;
|
|
2349
2419
|
}
|
|
2420
|
+
declare const DEFAULT_FAILURE_DETECTOR_CONFIG: FailureDetectorConfig;
|
|
2421
|
+
interface NodeState {
|
|
2422
|
+
/** Last heartbeat timestamp */
|
|
2423
|
+
lastHeartbeat: number;
|
|
2424
|
+
/** Heartbeat interval history for phi calculation */
|
|
2425
|
+
intervalHistory: number[];
|
|
2426
|
+
/** Whether node is currently suspected */
|
|
2427
|
+
isSuspected: boolean;
|
|
2428
|
+
/** Timestamp when suspicion started */
|
|
2429
|
+
suspicionStartTime?: number;
|
|
2430
|
+
/** Whether failure has been confirmed */
|
|
2431
|
+
isConfirmedFailed: boolean;
|
|
2432
|
+
}
|
|
2433
|
+
interface FailureDetectorEvents {
|
|
2434
|
+
nodeSuspected: {
|
|
2435
|
+
nodeId: string;
|
|
2436
|
+
phi: number;
|
|
2437
|
+
};
|
|
2438
|
+
nodeRecovered: {
|
|
2439
|
+
nodeId: string;
|
|
2440
|
+
};
|
|
2441
|
+
nodeConfirmedFailed: {
|
|
2442
|
+
nodeId: string;
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2350
2445
|
declare class FailureDetector extends EventEmitter {
|
|
2351
2446
|
private config;
|
|
2352
2447
|
private nodeStates;
|
|
@@ -2460,7 +2555,7 @@ interface ClusterMember {
|
|
|
2460
2555
|
isSelf: boolean;
|
|
2461
2556
|
}
|
|
2462
2557
|
interface ClusterMessage {
|
|
2463
|
-
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';
|
|
2558
|
+
type: 'HELLO' | 'MEMBER_LIST' | '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' | 'CLUSTER_MERKLE_ROOT_REQ' | 'CLUSTER_MERKLE_ROOT_RESP' | 'CLUSTER_MERKLE_BUCKETS_REQ' | 'CLUSTER_MERKLE_BUCKETS_RESP' | 'CLUSTER_MERKLE_KEYS_REQ' | 'CLUSTER_MERKLE_KEYS_RESP' | 'CLUSTER_REPAIR_DATA_REQ' | 'CLUSTER_REPAIR_DATA_RESP';
|
|
2464
2559
|
senderId: string;
|
|
2465
2560
|
payload: any;
|
|
2466
2561
|
}
|
|
@@ -2501,6 +2596,21 @@ declare class ClusterManager extends EventEmitter {
|
|
|
2501
2596
|
* Handle incoming heartbeat from a peer.
|
|
2502
2597
|
*/
|
|
2503
2598
|
private handleHeartbeat;
|
|
2599
|
+
/**
|
|
2600
|
+
* Send current member list to a specific node (gossip protocol).
|
|
2601
|
+
* Called when a new node joins to propagate cluster topology.
|
|
2602
|
+
*/
|
|
2603
|
+
private sendMemberList;
|
|
2604
|
+
/**
|
|
2605
|
+
* Broadcast member list to all connected nodes.
|
|
2606
|
+
* Called when cluster membership changes.
|
|
2607
|
+
*/
|
|
2608
|
+
private broadcastMemberList;
|
|
2609
|
+
/**
|
|
2610
|
+
* Handle incoming member list from a peer (gossip protocol).
|
|
2611
|
+
* Attempts to connect to unknown members.
|
|
2612
|
+
*/
|
|
2613
|
+
private handleMemberList;
|
|
2504
2614
|
/**
|
|
2505
2615
|
* Handle confirmed node failure.
|
|
2506
2616
|
*/
|
|
@@ -3187,6 +3297,505 @@ declare class ClusterCoordinator extends EventEmitter {
|
|
|
3187
3297
|
private setupEventHandlers;
|
|
3188
3298
|
}
|
|
3189
3299
|
|
|
3300
|
+
/**
|
|
3301
|
+
* PartitionReassigner - Automatic Partition Failover
|
|
3302
|
+
*
|
|
3303
|
+
* Handles automatic reassignment of partitions when nodes fail:
|
|
3304
|
+
* - Promotes backup nodes to owners
|
|
3305
|
+
* - Assigns new backups from remaining cluster
|
|
3306
|
+
* - Coordinates with MigrationManager for data transfer
|
|
3307
|
+
* - Broadcasts partition table updates
|
|
3308
|
+
*
|
|
3309
|
+
* This is Phase 10.02 of the TopGun cluster enhancements.
|
|
3310
|
+
*/
|
|
3311
|
+
|
|
3312
|
+
interface PartitionReassignerConfig {
|
|
3313
|
+
/** Delay before reassigning partitions after failure detection (ms). Default: 1000 */
|
|
3314
|
+
reassignmentDelayMs: number;
|
|
3315
|
+
/** Maximum concurrent partition transfers. Default: 10 */
|
|
3316
|
+
maxConcurrentTransfers: number;
|
|
3317
|
+
/** Enable automatic backup promotion. Default: true */
|
|
3318
|
+
autoPromoteBackups: boolean;
|
|
3319
|
+
/** Enable automatic new backup assignment. Default: true */
|
|
3320
|
+
autoAssignNewBackups: boolean;
|
|
3321
|
+
}
|
|
3322
|
+
declare const DEFAULT_REASSIGNER_CONFIG: PartitionReassignerConfig;
|
|
3323
|
+
interface ReassignmentEvent {
|
|
3324
|
+
type: 'backup-promoted' | 'new-backup-assigned' | 'reassignment-complete';
|
|
3325
|
+
partitionId: number;
|
|
3326
|
+
previousOwner?: string;
|
|
3327
|
+
newOwner?: string;
|
|
3328
|
+
backups?: string[];
|
|
3329
|
+
failedNodeId?: string;
|
|
3330
|
+
}
|
|
3331
|
+
interface FailoverStatus {
|
|
3332
|
+
inProgress: boolean;
|
|
3333
|
+
failedNodeId?: string;
|
|
3334
|
+
partitionsReassigned: number;
|
|
3335
|
+
partitionsPending: number;
|
|
3336
|
+
startedAt?: number;
|
|
3337
|
+
completedAt?: number;
|
|
3338
|
+
}
|
|
3339
|
+
declare class PartitionReassigner extends EventEmitter {
|
|
3340
|
+
private config;
|
|
3341
|
+
private clusterManager;
|
|
3342
|
+
private partitionService;
|
|
3343
|
+
private failoverInProgress;
|
|
3344
|
+
private currentFailedNode?;
|
|
3345
|
+
private reassignmentStartTime?;
|
|
3346
|
+
private partitionsReassigned;
|
|
3347
|
+
private pendingReassignments;
|
|
3348
|
+
private reassignmentTimer?;
|
|
3349
|
+
constructor(clusterManager: ClusterManager, partitionService: PartitionService, config?: Partial<PartitionReassignerConfig>);
|
|
3350
|
+
private setupEventHandlers;
|
|
3351
|
+
/**
|
|
3352
|
+
* Handle a node failure - initiates failover process
|
|
3353
|
+
*/
|
|
3354
|
+
private handleNodeFailure;
|
|
3355
|
+
/**
|
|
3356
|
+
* Handle a graceful node departure
|
|
3357
|
+
*/
|
|
3358
|
+
private handleNodeDeparture;
|
|
3359
|
+
/**
|
|
3360
|
+
* Execute the failover process for a failed node
|
|
3361
|
+
*/
|
|
3362
|
+
private executeFailover;
|
|
3363
|
+
/**
|
|
3364
|
+
* Find all partitions that need reassignment
|
|
3365
|
+
*/
|
|
3366
|
+
private findOrphanedPartitions;
|
|
3367
|
+
/**
|
|
3368
|
+
* Reassign a single partition
|
|
3369
|
+
*/
|
|
3370
|
+
private reassignPartition;
|
|
3371
|
+
/**
|
|
3372
|
+
* Select backup nodes for a partition
|
|
3373
|
+
*/
|
|
3374
|
+
private selectBackups;
|
|
3375
|
+
/**
|
|
3376
|
+
* Complete the failover process
|
|
3377
|
+
*/
|
|
3378
|
+
private completeFailover;
|
|
3379
|
+
/**
|
|
3380
|
+
* Get current failover status
|
|
3381
|
+
*/
|
|
3382
|
+
getStatus(): FailoverStatus;
|
|
3383
|
+
/**
|
|
3384
|
+
* Check if failover is in progress
|
|
3385
|
+
*/
|
|
3386
|
+
isFailoverInProgress(): boolean;
|
|
3387
|
+
/**
|
|
3388
|
+
* Force immediate reassignment (for testing/manual intervention)
|
|
3389
|
+
*/
|
|
3390
|
+
forceReassignment(failedNodeId: string): void;
|
|
3391
|
+
/**
|
|
3392
|
+
* Stop any pending reassignment
|
|
3393
|
+
*/
|
|
3394
|
+
stop(): void;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
/**
|
|
3398
|
+
* ReadReplicaHandler - Read Scaling via Replicas
|
|
3399
|
+
*
|
|
3400
|
+
* Phase 10.03: Enables reading from backup nodes to:
|
|
3401
|
+
* - Scale read throughput linearly with replicas
|
|
3402
|
+
* - Reduce latency by reading from nearest replica
|
|
3403
|
+
* - Provide availability during owner unavailability
|
|
3404
|
+
*
|
|
3405
|
+
* Supports three consistency levels for reads:
|
|
3406
|
+
* - STRONG: Read from partition owner (current behavior)
|
|
3407
|
+
* - EVENTUAL: Read from any replica (owner or backup)
|
|
3408
|
+
* - LOCAL: Read from local node if it's a replica
|
|
3409
|
+
*/
|
|
3410
|
+
|
|
3411
|
+
interface ReadReplicaConfig {
|
|
3412
|
+
/** Default consistency for reads. Default: STRONG */
|
|
3413
|
+
defaultConsistency: ConsistencyLevel;
|
|
3414
|
+
/** Maximum staleness for eventual reads in ms. Default: 5000 */
|
|
3415
|
+
maxStalenessMs: number;
|
|
3416
|
+
/** Prefer local replica over remote. Default: true */
|
|
3417
|
+
preferLocalReplica: boolean;
|
|
3418
|
+
/** Load balancing strategy for replica selection. Default: 'latency-based' */
|
|
3419
|
+
loadBalancing: 'round-robin' | 'least-connections' | 'latency-based';
|
|
3420
|
+
}
|
|
3421
|
+
declare const DEFAULT_READ_REPLICA_CONFIG: ReadReplicaConfig;
|
|
3422
|
+
interface ReadResult<T> {
|
|
3423
|
+
value: T | null;
|
|
3424
|
+
version?: Timestamp;
|
|
3425
|
+
source: string;
|
|
3426
|
+
isOwner: boolean;
|
|
3427
|
+
staleness?: number;
|
|
3428
|
+
}
|
|
3429
|
+
interface ReadRequest {
|
|
3430
|
+
mapName: string;
|
|
3431
|
+
key: string;
|
|
3432
|
+
options?: ClusterReadOptions;
|
|
3433
|
+
}
|
|
3434
|
+
declare class ReadReplicaHandler extends EventEmitter {
|
|
3435
|
+
private config;
|
|
3436
|
+
private partitionService;
|
|
3437
|
+
private clusterManager;
|
|
3438
|
+
private lagTracker?;
|
|
3439
|
+
private nodeId;
|
|
3440
|
+
private roundRobinCounters;
|
|
3441
|
+
constructor(partitionService: PartitionService, clusterManager: ClusterManager, nodeId: string, lagTracker?: LagTracker, config?: Partial<ReadReplicaConfig>);
|
|
3442
|
+
/**
|
|
3443
|
+
* Determine if a read request can be served locally
|
|
3444
|
+
*/
|
|
3445
|
+
canServeLocally(request: ReadRequest): boolean;
|
|
3446
|
+
/**
|
|
3447
|
+
* Determine which node should handle the read
|
|
3448
|
+
*/
|
|
3449
|
+
selectReadNode(request: ReadRequest): string | null;
|
|
3450
|
+
/**
|
|
3451
|
+
* Select replica using configured load balancing strategy
|
|
3452
|
+
*/
|
|
3453
|
+
private selectByStrategy;
|
|
3454
|
+
/**
|
|
3455
|
+
* Round-robin selection
|
|
3456
|
+
*/
|
|
3457
|
+
private selectRoundRobin;
|
|
3458
|
+
/**
|
|
3459
|
+
* Latency-based selection using lag tracker
|
|
3460
|
+
*/
|
|
3461
|
+
private selectByLatency;
|
|
3462
|
+
/**
|
|
3463
|
+
* Get estimated staleness for a node in ms
|
|
3464
|
+
*/
|
|
3465
|
+
private getNodeStaleness;
|
|
3466
|
+
/**
|
|
3467
|
+
* Check if a node is alive in the cluster
|
|
3468
|
+
*/
|
|
3469
|
+
private isNodeAlive;
|
|
3470
|
+
/**
|
|
3471
|
+
* Select first alive backup from list
|
|
3472
|
+
*/
|
|
3473
|
+
private selectAliveBackup;
|
|
3474
|
+
/**
|
|
3475
|
+
* Create read response metadata
|
|
3476
|
+
*/
|
|
3477
|
+
createReadMetadata(key: string, options?: ClusterReadOptions): {
|
|
3478
|
+
source: string;
|
|
3479
|
+
isOwner: boolean;
|
|
3480
|
+
consistency: ConsistencyLevel;
|
|
3481
|
+
};
|
|
3482
|
+
/**
|
|
3483
|
+
* Check if local node should forward read to owner
|
|
3484
|
+
*/
|
|
3485
|
+
shouldForwardRead(request: ReadRequest): boolean;
|
|
3486
|
+
/**
|
|
3487
|
+
* Get metrics for monitoring
|
|
3488
|
+
*/
|
|
3489
|
+
getMetrics(): {
|
|
3490
|
+
defaultConsistency: ConsistencyLevel;
|
|
3491
|
+
preferLocalReplica: boolean;
|
|
3492
|
+
loadBalancing: string;
|
|
3493
|
+
roundRobinPartitions: number;
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
/**
|
|
3498
|
+
* MerkleTreeManager - Per-Partition Merkle Tree Management
|
|
3499
|
+
*
|
|
3500
|
+
* Phase 10.04: Manages Merkle trees for each partition to enable:
|
|
3501
|
+
* - Efficient delta sync between nodes
|
|
3502
|
+
* - Anti-entropy repair detection
|
|
3503
|
+
* - Incremental updates on writes
|
|
3504
|
+
*
|
|
3505
|
+
* Each partition maintains its own Merkle tree for independent
|
|
3506
|
+
* consistency checking and repair.
|
|
3507
|
+
*/
|
|
3508
|
+
|
|
3509
|
+
interface MerkleTreeManagerConfig {
|
|
3510
|
+
/** Tree depth for Merkle trees. Default: 3 */
|
|
3511
|
+
treeDepth: number;
|
|
3512
|
+
/** Enable automatic tree updates on write. Default: true */
|
|
3513
|
+
autoUpdate: boolean;
|
|
3514
|
+
/** Lazy initialization of trees. Default: true */
|
|
3515
|
+
lazyInit: boolean;
|
|
3516
|
+
}
|
|
3517
|
+
declare const DEFAULT_MERKLE_TREE_CONFIG: MerkleTreeManagerConfig;
|
|
3518
|
+
interface MerkleComparisonResult {
|
|
3519
|
+
partitionId: number;
|
|
3520
|
+
localRoot: number;
|
|
3521
|
+
remoteRoot: number;
|
|
3522
|
+
needsSync: boolean;
|
|
3523
|
+
differingBuckets: string[];
|
|
3524
|
+
}
|
|
3525
|
+
interface PartitionMerkleInfo {
|
|
3526
|
+
partitionId: number;
|
|
3527
|
+
rootHash: number;
|
|
3528
|
+
keyCount: number;
|
|
3529
|
+
lastUpdated: number;
|
|
3530
|
+
}
|
|
3531
|
+
declare class MerkleTreeManager extends EventEmitter {
|
|
3532
|
+
private config;
|
|
3533
|
+
private trees;
|
|
3534
|
+
private keyCounts;
|
|
3535
|
+
private lastUpdated;
|
|
3536
|
+
private nodeId;
|
|
3537
|
+
constructor(nodeId: string, config?: Partial<MerkleTreeManagerConfig>);
|
|
3538
|
+
/**
|
|
3539
|
+
* Get or create a Merkle tree for a partition
|
|
3540
|
+
*/
|
|
3541
|
+
getTree(partitionId: number): MerkleTree;
|
|
3542
|
+
/**
|
|
3543
|
+
* Build tree for a partition from existing data
|
|
3544
|
+
*/
|
|
3545
|
+
buildTree(partitionId: number, records: Map<string, LWWRecord<any>>): void;
|
|
3546
|
+
/**
|
|
3547
|
+
* Incrementally update tree when a record changes
|
|
3548
|
+
*/
|
|
3549
|
+
updateRecord(partitionId: number, key: string, record: LWWRecord<any>): void;
|
|
3550
|
+
/**
|
|
3551
|
+
* Remove a key from the tree (e.g., after GC)
|
|
3552
|
+
*/
|
|
3553
|
+
removeRecord(partitionId: number, key: string): void;
|
|
3554
|
+
/**
|
|
3555
|
+
* Get the path prefix for a key in the Merkle tree
|
|
3556
|
+
*/
|
|
3557
|
+
private getKeyPath;
|
|
3558
|
+
/**
|
|
3559
|
+
* Get root hash for a partition
|
|
3560
|
+
*/
|
|
3561
|
+
getRootHash(partitionId: number): number;
|
|
3562
|
+
/**
|
|
3563
|
+
* Compare local tree with remote root hash
|
|
3564
|
+
*/
|
|
3565
|
+
compareWithRemote(partitionId: number, remoteRoot: number): MerkleComparisonResult;
|
|
3566
|
+
/**
|
|
3567
|
+
* Find buckets that differ between local and remote tree
|
|
3568
|
+
* Note: This is a simplified version - full implementation would
|
|
3569
|
+
* need to exchange bucket hashes with the remote node
|
|
3570
|
+
*/
|
|
3571
|
+
private findDifferingBuckets;
|
|
3572
|
+
/**
|
|
3573
|
+
* Recursively collect all leaf bucket paths
|
|
3574
|
+
*/
|
|
3575
|
+
private collectLeafBuckets;
|
|
3576
|
+
/**
|
|
3577
|
+
* Get bucket hashes for a partition at a given path
|
|
3578
|
+
*/
|
|
3579
|
+
getBuckets(partitionId: number, path: string): Record<string, number>;
|
|
3580
|
+
/**
|
|
3581
|
+
* Get keys in a specific bucket
|
|
3582
|
+
*/
|
|
3583
|
+
getKeysInBucket(partitionId: number, path: string): string[];
|
|
3584
|
+
/**
|
|
3585
|
+
* Get all keys across all buckets for a partition
|
|
3586
|
+
*/
|
|
3587
|
+
getAllKeys(partitionId: number): string[];
|
|
3588
|
+
/**
|
|
3589
|
+
* Recursively collect all keys from the tree
|
|
3590
|
+
*/
|
|
3591
|
+
private collectAllKeys;
|
|
3592
|
+
/**
|
|
3593
|
+
* Get info about all managed partitions
|
|
3594
|
+
*/
|
|
3595
|
+
getPartitionInfos(): PartitionMerkleInfo[];
|
|
3596
|
+
/**
|
|
3597
|
+
* Get info for a specific partition
|
|
3598
|
+
*/
|
|
3599
|
+
getPartitionInfo(partitionId: number): PartitionMerkleInfo | null;
|
|
3600
|
+
/**
|
|
3601
|
+
* Clear tree for a partition (e.g., after migration)
|
|
3602
|
+
*/
|
|
3603
|
+
clearPartition(partitionId: number): void;
|
|
3604
|
+
/**
|
|
3605
|
+
* Clear all trees
|
|
3606
|
+
*/
|
|
3607
|
+
clearAll(): void;
|
|
3608
|
+
/**
|
|
3609
|
+
* Get metrics for monitoring
|
|
3610
|
+
*/
|
|
3611
|
+
getMetrics(): {
|
|
3612
|
+
totalPartitions: number;
|
|
3613
|
+
totalKeys: number;
|
|
3614
|
+
averageKeysPerPartition: number;
|
|
3615
|
+
};
|
|
3616
|
+
/**
|
|
3617
|
+
* Serialize tree state for network transfer
|
|
3618
|
+
*/
|
|
3619
|
+
serializeTree(partitionId: number): {
|
|
3620
|
+
rootHash: number;
|
|
3621
|
+
buckets: Record<string, Record<string, number>>;
|
|
3622
|
+
} | null;
|
|
3623
|
+
private collectBucketsAtDepth;
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
/**
|
|
3627
|
+
* RepairScheduler - Anti-Entropy Repair System
|
|
3628
|
+
*
|
|
3629
|
+
* Phase 10.04: Proactively detects and repairs data inconsistencies:
|
|
3630
|
+
* - Periodic scanning of partitions
|
|
3631
|
+
* - Merkle tree-based difference detection
|
|
3632
|
+
* - LWW conflict resolution
|
|
3633
|
+
* - Throttled repair execution
|
|
3634
|
+
*
|
|
3635
|
+
* Based on Cassandra/Dynamo anti-entropy patterns.
|
|
3636
|
+
*/
|
|
3637
|
+
|
|
3638
|
+
interface RepairConfig {
|
|
3639
|
+
/** Enable anti-entropy repair. Default: true */
|
|
3640
|
+
enabled: boolean;
|
|
3641
|
+
/** Interval between full scans in ms. Default: 3600000 (1 hour) */
|
|
3642
|
+
scanIntervalMs: number;
|
|
3643
|
+
/** Keys per repair batch. Default: 1000 */
|
|
3644
|
+
repairBatchSize: number;
|
|
3645
|
+
/** Maximum concurrent partition repairs. Default: 2 */
|
|
3646
|
+
maxConcurrentRepairs: number;
|
|
3647
|
+
/** Delay between batches in ms. Default: 100 */
|
|
3648
|
+
throttleMs: number;
|
|
3649
|
+
/** Prioritize recently modified partitions. Default: true */
|
|
3650
|
+
prioritizeRecent: boolean;
|
|
3651
|
+
/** Timeout for network requests in ms. Default: 5000 */
|
|
3652
|
+
requestTimeoutMs: number;
|
|
3653
|
+
}
|
|
3654
|
+
declare const DEFAULT_REPAIR_CONFIG: RepairConfig;
|
|
3655
|
+
interface RepairTask {
|
|
3656
|
+
partitionId: number;
|
|
3657
|
+
replicaNodeId: string;
|
|
3658
|
+
priority: 'high' | 'normal' | 'low';
|
|
3659
|
+
scheduledAt: number;
|
|
3660
|
+
}
|
|
3661
|
+
interface RepairResult {
|
|
3662
|
+
partitionId: number;
|
|
3663
|
+
replicaNodeId: string;
|
|
3664
|
+
keysScanned: number;
|
|
3665
|
+
keysRepaired: number;
|
|
3666
|
+
durationMs: number;
|
|
3667
|
+
success: boolean;
|
|
3668
|
+
error?: string;
|
|
3669
|
+
}
|
|
3670
|
+
interface RepairMetrics {
|
|
3671
|
+
scansCompleted: number;
|
|
3672
|
+
repairsExecuted: number;
|
|
3673
|
+
keysRepaired: number;
|
|
3674
|
+
errorsEncountered: number;
|
|
3675
|
+
lastScanTime?: number;
|
|
3676
|
+
averageRepairDurationMs: number;
|
|
3677
|
+
}
|
|
3678
|
+
type RecordGetter = (key: string) => LWWRecord<any> | undefined;
|
|
3679
|
+
type RecordSetter = (key: string, record: LWWRecord<any>) => void;
|
|
3680
|
+
declare class RepairScheduler extends EventEmitter {
|
|
3681
|
+
private config;
|
|
3682
|
+
private merkleManager;
|
|
3683
|
+
private clusterManager;
|
|
3684
|
+
private partitionService;
|
|
3685
|
+
private nodeId;
|
|
3686
|
+
private repairQueue;
|
|
3687
|
+
private activeRepairs;
|
|
3688
|
+
private scanTimer?;
|
|
3689
|
+
private processTimer?;
|
|
3690
|
+
private started;
|
|
3691
|
+
private pendingRequests;
|
|
3692
|
+
private metrics;
|
|
3693
|
+
private getRecord?;
|
|
3694
|
+
private setRecord?;
|
|
3695
|
+
constructor(merkleManager: MerkleTreeManager, clusterManager: ClusterManager, partitionService: PartitionService, nodeId: string, config?: Partial<RepairConfig>);
|
|
3696
|
+
/**
|
|
3697
|
+
* Set data access callbacks
|
|
3698
|
+
*/
|
|
3699
|
+
setDataAccessors(getRecord: RecordGetter, setRecord: RecordSetter): void;
|
|
3700
|
+
/**
|
|
3701
|
+
* Setup network message handlers
|
|
3702
|
+
*/
|
|
3703
|
+
private setupNetworkHandlers;
|
|
3704
|
+
/**
|
|
3705
|
+
* Handle incoming cluster messages
|
|
3706
|
+
*/
|
|
3707
|
+
private handleClusterMessage;
|
|
3708
|
+
private handleMerkleRootReq;
|
|
3709
|
+
private handleMerkleBucketsReq;
|
|
3710
|
+
private handleMerkleKeysReq;
|
|
3711
|
+
private handleRepairDataReq;
|
|
3712
|
+
private handleResponse;
|
|
3713
|
+
/**
|
|
3714
|
+
* Start the repair scheduler
|
|
3715
|
+
*/
|
|
3716
|
+
start(): void;
|
|
3717
|
+
/**
|
|
3718
|
+
* Stop the repair scheduler
|
|
3719
|
+
*/
|
|
3720
|
+
stop(): void;
|
|
3721
|
+
/**
|
|
3722
|
+
* Schedule a full scan of all owned partitions
|
|
3723
|
+
*/
|
|
3724
|
+
scheduleFullScan(): void;
|
|
3725
|
+
/**
|
|
3726
|
+
* Schedule repair for a specific partition
|
|
3727
|
+
*/
|
|
3728
|
+
schedulePartitionRepair(partitionId: number, priority?: 'high' | 'normal' | 'low'): void;
|
|
3729
|
+
/**
|
|
3730
|
+
* Sort repair queue by priority
|
|
3731
|
+
*/
|
|
3732
|
+
private sortRepairQueue;
|
|
3733
|
+
/**
|
|
3734
|
+
* Process the repair queue
|
|
3735
|
+
*/
|
|
3736
|
+
private processRepairQueue;
|
|
3737
|
+
/**
|
|
3738
|
+
* Execute repair for a partition-replica pair
|
|
3739
|
+
*/
|
|
3740
|
+
private executeRepair;
|
|
3741
|
+
/**
|
|
3742
|
+
* Send a request and wait for response
|
|
3743
|
+
*/
|
|
3744
|
+
private sendRequest;
|
|
3745
|
+
/**
|
|
3746
|
+
* Request Merkle root from remote node
|
|
3747
|
+
*/
|
|
3748
|
+
private requestRemoteMerkleRoot;
|
|
3749
|
+
/**
|
|
3750
|
+
* Find keys that differ between local and remote using bucket exchange
|
|
3751
|
+
*/
|
|
3752
|
+
private findDifferences;
|
|
3753
|
+
/**
|
|
3754
|
+
* Repair a single key
|
|
3755
|
+
*/
|
|
3756
|
+
private repairKey;
|
|
3757
|
+
/**
|
|
3758
|
+
* Resolve conflict between two records using LWW
|
|
3759
|
+
*/
|
|
3760
|
+
resolveConflict<T>(a: LWWRecord<T> | undefined, b: LWWRecord<T> | undefined): LWWRecord<T> | null;
|
|
3761
|
+
/**
|
|
3762
|
+
* Compare two timestamps
|
|
3763
|
+
*/
|
|
3764
|
+
private compareTimestamps;
|
|
3765
|
+
/**
|
|
3766
|
+
* Get partitions owned by this node
|
|
3767
|
+
*/
|
|
3768
|
+
private getOwnedPartitions;
|
|
3769
|
+
/**
|
|
3770
|
+
* Get partitions where this node is a backup
|
|
3771
|
+
*/
|
|
3772
|
+
private getReplicaPartitions;
|
|
3773
|
+
/**
|
|
3774
|
+
* Update average repair duration
|
|
3775
|
+
*/
|
|
3776
|
+
private updateAverageRepairDuration;
|
|
3777
|
+
/**
|
|
3778
|
+
* Get repair metrics
|
|
3779
|
+
*/
|
|
3780
|
+
getMetrics(): RepairMetrics;
|
|
3781
|
+
/**
|
|
3782
|
+
* Get repair queue status
|
|
3783
|
+
*/
|
|
3784
|
+
getQueueStatus(): {
|
|
3785
|
+
queueLength: number;
|
|
3786
|
+
activeRepairs: number;
|
|
3787
|
+
maxConcurrent: number;
|
|
3788
|
+
};
|
|
3789
|
+
/**
|
|
3790
|
+
* Force immediate repair for a partition
|
|
3791
|
+
*/
|
|
3792
|
+
forceRepair(partitionId: number): void;
|
|
3793
|
+
/**
|
|
3794
|
+
* Sleep utility
|
|
3795
|
+
*/
|
|
3796
|
+
private sleep;
|
|
3797
|
+
}
|
|
3798
|
+
|
|
3190
3799
|
/**
|
|
3191
3800
|
* Configuration for the processor sandbox.
|
|
3192
3801
|
*/
|
|
@@ -3872,4 +4481,266 @@ declare class MapFactory {
|
|
|
3872
4481
|
getConfig(): ServerIndexConfig;
|
|
3873
4482
|
}
|
|
3874
4483
|
|
|
3875
|
-
|
|
4484
|
+
/**
|
|
4485
|
+
* SearchCoordinator - Server-side Full-Text Search Handler
|
|
4486
|
+
*
|
|
4487
|
+
* Manages FullTextIndex instances per map and handles search requests.
|
|
4488
|
+
* Part of Phase 11.1a: Server-side BM25 Search.
|
|
4489
|
+
* Phase 11.1b: Live Search Subscriptions with delta updates.
|
|
4490
|
+
*
|
|
4491
|
+
* @module search/SearchCoordinator
|
|
4492
|
+
*/
|
|
4493
|
+
|
|
4494
|
+
/**
|
|
4495
|
+
* Result item returned from server search.
|
|
4496
|
+
*/
|
|
4497
|
+
interface ServerSearchResult {
|
|
4498
|
+
key: string;
|
|
4499
|
+
value: unknown;
|
|
4500
|
+
score: number;
|
|
4501
|
+
matchedTerms: string[];
|
|
4502
|
+
}
|
|
4503
|
+
/**
|
|
4504
|
+
* Configuration for enabling search on a map.
|
|
4505
|
+
*/
|
|
4506
|
+
interface SearchConfig extends FullTextIndexConfig {
|
|
4507
|
+
}
|
|
4508
|
+
/**
|
|
4509
|
+
* Callback type for sending updates to clients.
|
|
4510
|
+
*/
|
|
4511
|
+
type SendUpdateCallback = (clientId: string, subscriptionId: string, key: string, value: unknown, score: number, matchedTerms: string[], type: SearchUpdateType) => void;
|
|
4512
|
+
/**
|
|
4513
|
+
* Batched update for a single document change.
|
|
4514
|
+
*/
|
|
4515
|
+
interface BatchedUpdate {
|
|
4516
|
+
key: string;
|
|
4517
|
+
value: unknown;
|
|
4518
|
+
score: number;
|
|
4519
|
+
matchedTerms: string[];
|
|
4520
|
+
type: SearchUpdateType;
|
|
4521
|
+
}
|
|
4522
|
+
/**
|
|
4523
|
+
* Callback type for sending batched updates to clients.
|
|
4524
|
+
*/
|
|
4525
|
+
type SendBatchUpdateCallback = (clientId: string, subscriptionId: string, updates: BatchedUpdate[]) => void;
|
|
4526
|
+
/**
|
|
4527
|
+
* SearchCoordinator manages full-text search indexes for the server.
|
|
4528
|
+
*
|
|
4529
|
+
* Responsibilities:
|
|
4530
|
+
* - Maintain FullTextIndex per enabled map
|
|
4531
|
+
* - Execute one-shot search queries
|
|
4532
|
+
* - Update indexes when data changes
|
|
4533
|
+
*
|
|
4534
|
+
* @example
|
|
4535
|
+
* ```typescript
|
|
4536
|
+
* const searchCoordinator = new SearchCoordinator();
|
|
4537
|
+
*
|
|
4538
|
+
* // Enable FTS for a map
|
|
4539
|
+
* searchCoordinator.enableSearch('articles', {
|
|
4540
|
+
* fields: ['title', 'body'],
|
|
4541
|
+
* tokenizer: { minLength: 2 },
|
|
4542
|
+
* bm25: { k1: 1.2, b: 0.75 }
|
|
4543
|
+
* });
|
|
4544
|
+
*
|
|
4545
|
+
* // Search
|
|
4546
|
+
* const results = searchCoordinator.search('articles', 'machine learning', {
|
|
4547
|
+
* limit: 20,
|
|
4548
|
+
* boost: { title: 2.0 }
|
|
4549
|
+
* });
|
|
4550
|
+
* ```
|
|
4551
|
+
*/
|
|
4552
|
+
declare class SearchCoordinator {
|
|
4553
|
+
/** Map name → FullTextIndex */
|
|
4554
|
+
private readonly indexes;
|
|
4555
|
+
/** Map name → FullTextIndexConfig (for reference) */
|
|
4556
|
+
private readonly configs;
|
|
4557
|
+
/** Callback to get document value by key (injected by ServerCoordinator) */
|
|
4558
|
+
private getDocumentValue?;
|
|
4559
|
+
/** Subscription ID → SearchSubscription */
|
|
4560
|
+
private readonly subscriptions;
|
|
4561
|
+
/** Map name → Set of subscription IDs */
|
|
4562
|
+
private readonly subscriptionsByMap;
|
|
4563
|
+
/** Client ID → Set of subscription IDs */
|
|
4564
|
+
private readonly subscriptionsByClient;
|
|
4565
|
+
/** Callback for sending updates to clients */
|
|
4566
|
+
private sendUpdate?;
|
|
4567
|
+
/** Callback for sending batched updates to clients */
|
|
4568
|
+
private sendBatchUpdate?;
|
|
4569
|
+
/** Queue of pending notifications per map */
|
|
4570
|
+
private readonly pendingNotifications;
|
|
4571
|
+
/** Timer for batching notifications */
|
|
4572
|
+
private notificationTimer;
|
|
4573
|
+
/** Batch interval in milliseconds (~1 frame at 60fps) */
|
|
4574
|
+
private readonly BATCH_INTERVAL;
|
|
4575
|
+
constructor();
|
|
4576
|
+
/**
|
|
4577
|
+
* Set the callback for sending updates to clients.
|
|
4578
|
+
* Called by ServerCoordinator during initialization.
|
|
4579
|
+
*/
|
|
4580
|
+
setSendUpdateCallback(callback: SendUpdateCallback): void;
|
|
4581
|
+
/**
|
|
4582
|
+
* Set the callback for sending batched updates to clients.
|
|
4583
|
+
* When set, notifications are batched within BATCH_INTERVAL (16ms) window.
|
|
4584
|
+
* Called by ServerCoordinator during initialization.
|
|
4585
|
+
*
|
|
4586
|
+
* @param callback - Function to call with batched updates
|
|
4587
|
+
*/
|
|
4588
|
+
setSendBatchUpdateCallback(callback: SendBatchUpdateCallback): void;
|
|
4589
|
+
/**
|
|
4590
|
+
* Set the callback for retrieving document values.
|
|
4591
|
+
* Called by ServerCoordinator during initialization.
|
|
4592
|
+
*/
|
|
4593
|
+
setDocumentValueGetter(getter: (mapName: string, key: string) => unknown | undefined): void;
|
|
4594
|
+
/**
|
|
4595
|
+
* Enable full-text search for a map.
|
|
4596
|
+
*
|
|
4597
|
+
* @param mapName - Name of the map to enable FTS for
|
|
4598
|
+
* @param config - FTS configuration (fields, tokenizer, bm25 options)
|
|
4599
|
+
*/
|
|
4600
|
+
enableSearch(mapName: string, config: SearchConfig): void;
|
|
4601
|
+
/**
|
|
4602
|
+
* Disable full-text search for a map.
|
|
4603
|
+
*
|
|
4604
|
+
* @param mapName - Name of the map to disable FTS for
|
|
4605
|
+
*/
|
|
4606
|
+
disableSearch(mapName: string): void;
|
|
4607
|
+
/**
|
|
4608
|
+
* Check if FTS is enabled for a map.
|
|
4609
|
+
*/
|
|
4610
|
+
isSearchEnabled(mapName: string): boolean;
|
|
4611
|
+
/**
|
|
4612
|
+
* Get enabled map names.
|
|
4613
|
+
*/
|
|
4614
|
+
getEnabledMaps(): string[];
|
|
4615
|
+
/**
|
|
4616
|
+
* Execute a one-shot search query.
|
|
4617
|
+
*
|
|
4618
|
+
* @param mapName - Name of the map to search
|
|
4619
|
+
* @param query - Search query text
|
|
4620
|
+
* @param options - Search options (limit, minScore, boost)
|
|
4621
|
+
* @returns Search response payload
|
|
4622
|
+
*/
|
|
4623
|
+
search(mapName: string, query: string, options?: FTSSearchOptions): SearchRespPayload;
|
|
4624
|
+
/**
|
|
4625
|
+
* Handle document set/update.
|
|
4626
|
+
* Called by ServerCoordinator when data changes.
|
|
4627
|
+
*
|
|
4628
|
+
* @param mapName - Name of the map
|
|
4629
|
+
* @param key - Document key
|
|
4630
|
+
* @param value - Document value
|
|
4631
|
+
*/
|
|
4632
|
+
onDataChange(mapName: string, key: string, value: Record<string, unknown> | null | undefined, changeType: 'add' | 'update' | 'remove'): void;
|
|
4633
|
+
/**
|
|
4634
|
+
* Build index from existing map entries.
|
|
4635
|
+
* Called when FTS is enabled for a map that already has data.
|
|
4636
|
+
*
|
|
4637
|
+
* @param mapName - Name of the map
|
|
4638
|
+
* @param entries - Iterator of [key, value] tuples
|
|
4639
|
+
*/
|
|
4640
|
+
buildIndexFromEntries(mapName: string, entries: Iterable<[string, Record<string, unknown> | null]>): void;
|
|
4641
|
+
/**
|
|
4642
|
+
* Get index statistics for monitoring.
|
|
4643
|
+
*/
|
|
4644
|
+
getIndexStats(mapName: string): {
|
|
4645
|
+
documentCount: number;
|
|
4646
|
+
fields: string[];
|
|
4647
|
+
} | null;
|
|
4648
|
+
/**
|
|
4649
|
+
* Clear all indexes (for testing or shutdown).
|
|
4650
|
+
*/
|
|
4651
|
+
clear(): void;
|
|
4652
|
+
/**
|
|
4653
|
+
* Subscribe to live search results.
|
|
4654
|
+
* Returns initial results and tracks the subscription for delta updates.
|
|
4655
|
+
*
|
|
4656
|
+
* @param clientId - ID of the subscribing client
|
|
4657
|
+
* @param subscriptionId - Unique subscription identifier
|
|
4658
|
+
* @param mapName - Name of the map to search
|
|
4659
|
+
* @param query - Search query text
|
|
4660
|
+
* @param options - Search options (limit, minScore, boost)
|
|
4661
|
+
* @returns Initial search results
|
|
4662
|
+
*/
|
|
4663
|
+
subscribe(clientId: string, subscriptionId: string, mapName: string, query: string, options?: SearchOptions): ServerSearchResult[];
|
|
4664
|
+
/**
|
|
4665
|
+
* Unsubscribe from a live search.
|
|
4666
|
+
*
|
|
4667
|
+
* @param subscriptionId - Subscription to remove
|
|
4668
|
+
*/
|
|
4669
|
+
unsubscribe(subscriptionId: string): void;
|
|
4670
|
+
/**
|
|
4671
|
+
* Unsubscribe all subscriptions for a client.
|
|
4672
|
+
* Called when a client disconnects.
|
|
4673
|
+
*
|
|
4674
|
+
* @param clientId - ID of the disconnected client
|
|
4675
|
+
*/
|
|
4676
|
+
unsubscribeClient(clientId: string): void;
|
|
4677
|
+
/**
|
|
4678
|
+
* Get the number of active subscriptions.
|
|
4679
|
+
*/
|
|
4680
|
+
getSubscriptionCount(): number;
|
|
4681
|
+
/**
|
|
4682
|
+
* Notify subscribers about a document change.
|
|
4683
|
+
* Computes delta (ENTER/UPDATE/LEAVE) for each affected subscription.
|
|
4684
|
+
*
|
|
4685
|
+
* @param mapName - Name of the map that changed
|
|
4686
|
+
* @param key - Document key that changed
|
|
4687
|
+
* @param value - New document value (null if removed)
|
|
4688
|
+
* @param changeType - Type of change
|
|
4689
|
+
*/
|
|
4690
|
+
private notifySubscribers;
|
|
4691
|
+
/**
|
|
4692
|
+
* Score a single document against a subscription's query.
|
|
4693
|
+
*
|
|
4694
|
+
* OPTIMIZED: O(Q × D) complexity instead of O(N) full index scan.
|
|
4695
|
+
* Uses pre-tokenized queryTerms and FullTextIndex.scoreSingleDocument().
|
|
4696
|
+
*
|
|
4697
|
+
* @param subscription - The subscription containing query and cached queryTerms
|
|
4698
|
+
* @param key - Document key
|
|
4699
|
+
* @param value - Document value
|
|
4700
|
+
* @param index - The FullTextIndex for this map
|
|
4701
|
+
* @returns Scored result or null if document doesn't match
|
|
4702
|
+
*/
|
|
4703
|
+
private scoreDocument;
|
|
4704
|
+
/**
|
|
4705
|
+
* Queue a notification for batched processing.
|
|
4706
|
+
* Notifications are collected and processed together after BATCH_INTERVAL.
|
|
4707
|
+
*
|
|
4708
|
+
* @param mapName - Name of the map that changed
|
|
4709
|
+
* @param key - Document key that changed
|
|
4710
|
+
* @param value - New document value (null if removed)
|
|
4711
|
+
* @param changeType - Type of change
|
|
4712
|
+
*/
|
|
4713
|
+
queueNotification(mapName: string, key: string, value: Record<string, unknown> | null, changeType: 'add' | 'update' | 'remove'): void;
|
|
4714
|
+
/**
|
|
4715
|
+
* Schedule a flush of pending notifications.
|
|
4716
|
+
* Uses setTimeout to batch notifications within BATCH_INTERVAL window.
|
|
4717
|
+
*/
|
|
4718
|
+
private scheduleNotificationFlush;
|
|
4719
|
+
/**
|
|
4720
|
+
* Flush all pending notifications.
|
|
4721
|
+
* Processes each map's notifications and sends batched updates.
|
|
4722
|
+
*/
|
|
4723
|
+
flushNotifications(): void;
|
|
4724
|
+
/**
|
|
4725
|
+
* Process batched notifications for a single map.
|
|
4726
|
+
* Computes updates for each subscription and sends as a batch.
|
|
4727
|
+
*
|
|
4728
|
+
* @param mapName - Name of the map
|
|
4729
|
+
* @param notifications - Array of pending notifications
|
|
4730
|
+
*/
|
|
4731
|
+
private processBatchedNotifications;
|
|
4732
|
+
/**
|
|
4733
|
+
* Compute the update for a single document change against a subscription.
|
|
4734
|
+
* Returns null if no update is needed.
|
|
4735
|
+
*
|
|
4736
|
+
* @param subscription - The subscription to check
|
|
4737
|
+
* @param key - Document key
|
|
4738
|
+
* @param value - Document value (null if removed)
|
|
4739
|
+
* @param changeType - Type of change
|
|
4740
|
+
* @param index - The FullTextIndex for this map
|
|
4741
|
+
* @returns BatchedUpdate or null
|
|
4742
|
+
*/
|
|
4743
|
+
private computeSubscriptionUpdate;
|
|
4744
|
+
}
|
|
4745
|
+
|
|
4746
|
+
export { BufferPool, type BufferPoolConfig, type BufferPoolStats, type ClusterConfig, ClusterCoordinator, type ClusterCoordinatorConfig, type ClusterCoordinatorEvents, ClusterManager, type ClusterMember, type ClusterMessage, type CoalescingPreset, type CoalescingWriterMetrics, type CoalescingWriterOptions, ConflictResolverHandler, type ConflictResolverHandlerConfig, ConflictResolverService, type ConflictResolverServiceConfig, type ConnectionContext, ConnectionRateLimiter, DEFAULT_CLUSTER_COORDINATOR_CONFIG, DEFAULT_CONFLICT_RESOLVER_CONFIG, DEFAULT_FAILURE_DETECTOR_CONFIG, DEFAULT_INDEX_CONFIG, DEFAULT_JOURNAL_SERVICE_CONFIG, DEFAULT_LAG_TRACKER_CONFIG, DEFAULT_MERKLE_TREE_CONFIG, DEFAULT_READ_REPLICA_CONFIG, DEFAULT_REASSIGNER_CONFIG, DEFAULT_REPAIR_CONFIG, DEFAULT_SANDBOX_CONFIG, EntryProcessorHandler, type EntryProcessorHandlerConfig, EventJournalService, type EventJournalServiceConfig, type ExportOptions, type FailoverStatus, FailureDetector, type FailureDetectorConfig, type FailureDetectorEvents, FilterTasklet, ForEachTasklet, type IInterceptor, type IServerStorage, type IndexDefinition, IteratorTasklet, type IteratorTaskletConfig, type LagInfo, LagTracker, type LagTrackerConfig, LockManager, type Logger, MapFactory, type MapIndexConfig, MapTasklet, MapWithResolver, type MapWithResolverConfig, MemoryServerAdapter, type MergeWithResolverResult, type MerkleComparisonResult, MerkleTreeManager, type MerkleTreeManagerConfig, MigrationManager, type NativeModuleStatus, type NativeStats, type NodeState, type ORMapTombstones, type ORMapValue, ObjectPool, type ObjectPoolConfig, type ObjectPoolStats, type OpContext, type PartitionDistribution, type PartitionMerkleInfo, PartitionReassigner, type PartitionReassignerConfig, PartitionService, type PartitionServiceConfig, type PartitionServiceEvents, type PooledEventPayload, type PooledMessage, type PooledRecord, type PooledTimestamp, PostgresAdapter, type PostgresAdapterOptions, ProcessorSandbox, type ProcessorSandboxConfig, type ProgressState, RateLimitInterceptor, type RateLimiterConfig, type RateLimiterStats, type ReadReplicaConfig, ReadReplicaHandler, type ReadRequest, type ReadResult, type ReassignmentEvent, ReduceTasklet, type RepairConfig, type RepairMetrics, type RepairResult, RepairScheduler, type RepairTask, ReplicationPipeline, type SearchConfig, SearchCoordinator, SecurityManager, ServerCoordinator, type ServerCoordinatorConfig, type ServerIndexConfig, type ServerOp, type ServerSearchResult, type SetWithResolverResult, 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, mergeWithDefaults, setGlobalBufferPool, setGlobalEventPayloadPool, setGlobalMessagePool, setGlobalRecordPool, setGlobalTimestampPool, validateIndexConfig };
|