@topgunbuild/server 0.9.0 → 0.10.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 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, 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';
2
+ import { Timestamp, LWWRecord, ORMapRecord, Principal, EventJournalImpl, EventJournalConfig, JournalEvent, SearchUpdateType, FullTextIndexConfig, FTSSearchOptions, SearchRespPayload, SearchOptions, MigrationConfig, MigrationStatus, MigrationMetrics, PartitionMap, PartitionInfo, PartitionChange, PermissionPolicy, ConsistencyLevel, ReplicationConfig, LWWMap, ORMap, PermissionType, ReplicationLag, ReplicationHealth, ReplicationResult, ClusterReadOptions, MerkleTree, EntryProcessorDef, EntryProcessorResult, HLC, MergeRejection, ConflictResolverDef, MergeContext, MergeResult, IndexedLWWMap, IndexedORMap } from '@topgunbuild/core';
3
3
  import { WebSocket } from 'ws';
4
4
  import { Pool, PoolConfig } from 'pg';
5
5
  import pino from 'pino';
@@ -1782,1085 +1782,1454 @@ declare class EventJournalService extends EventJournalImpl {
1782
1782
  getPendingPersistCount(): number;
1783
1783
  }
1784
1784
 
1785
- interface ServerCoordinatorConfig {
1786
- port: number;
1787
- nodeId: string;
1788
- storage?: IServerStorage;
1789
- jwtSecret?: string;
1790
- host?: string;
1791
- clusterPort?: number;
1792
- peers?: string[];
1793
- securityPolicies?: PermissionPolicy[];
1794
- /** Callback to resolve dynamic peer addresses after ports are known */
1795
- resolvePeers?: () => string[];
1796
- interceptors?: IInterceptor[];
1797
- metricsPort?: number;
1798
- discovery?: 'manual' | 'kubernetes';
1799
- serviceName?: string;
1800
- discoveryInterval?: number;
1801
- tls?: TLSConfig;
1802
- clusterTls?: ClusterTLSConfig;
1803
- /** Total event queue capacity for bounded queue (default: 10000) */
1804
- eventQueueCapacity?: number;
1805
- /** Number of event queue stripes for parallel processing (default: 4) */
1806
- eventStripeCount?: number;
1807
- /** Enable/disable backpressure (default: true) */
1808
- backpressureEnabled?: boolean;
1809
- /** How often to force sync processing (default: 100 operations) */
1810
- backpressureSyncFrequency?: number;
1811
- /** Maximum pending async operations before blocking (default: 1000) */
1812
- backpressureMaxPending?: number;
1813
- /** Backoff timeout in ms when at capacity (default: 5000) */
1814
- backpressureBackoffMs?: number;
1815
- /** Enable/disable write coalescing (default: true) */
1816
- writeCoalescingEnabled?: boolean;
1817
- /** Coalescing preset: 'conservative', 'balanced', 'highThroughput', 'aggressive' (default: 'highThroughput') */
1818
- writeCoalescingPreset?: CoalescingPreset;
1819
- /** Maximum messages to batch before forcing flush (default: 500 for highThroughput) */
1820
- writeCoalescingMaxBatch?: number;
1821
- /** Maximum delay before flushing in ms (default: 10 for highThroughput) */
1822
- writeCoalescingMaxDelayMs?: number;
1823
- /** Maximum batch size in bytes (default: 262144/256KB for highThroughput) */
1824
- writeCoalescingMaxBytes?: number;
1825
- /** WebSocket backlog for pending connections (default: 511) */
1826
- wsBacklog?: number;
1827
- /** Enable WebSocket per-message compression (default: false for CPU savings) */
1828
- wsCompression?: boolean;
1829
- /** Maximum WebSocket payload size in bytes (default: 64MB) */
1830
- wsMaxPayload?: number;
1831
- /** Maximum server connections (default: 10000) */
1832
- maxConnections?: number;
1833
- /** Server timeout in ms (default: 120000 = 2 min) */
1834
- serverTimeout?: number;
1835
- /** Keep-alive timeout in ms (default: 5000) */
1836
- keepAliveTimeout?: number;
1837
- /** Headers timeout in ms (default: 60000) */
1838
- headersTimeout?: number;
1839
- /** Enable connection rate limiting (default: true) */
1840
- rateLimitingEnabled?: boolean;
1841
- /** Maximum new connections per second (default: 100) */
1842
- maxConnectionsPerSecond?: number;
1843
- /** Maximum pending connections (default: 1000) */
1844
- maxPendingConnections?: number;
1845
- /** Enable worker pool for CPU-bound operations (default: false) */
1846
- workerPoolEnabled?: boolean;
1847
- /** Worker pool configuration */
1848
- workerPoolConfig?: Partial<WorkerPoolConfig>;
1849
- /** Default timeout for Write Concern acknowledgments in ms (default: 5000) */
1850
- writeAckTimeout?: number;
1851
- /** Enable replication to backup nodes (default: true when cluster has peers) */
1852
- replicationEnabled?: boolean;
1853
- /** Default consistency level for replication (default: EVENTUAL) */
1854
- defaultConsistency?: ConsistencyLevel;
1855
- /** Replication configuration */
1856
- replicationConfig?: Partial<ReplicationConfig>;
1857
- /** Enable event journal for audit/CDC (default: false) */
1858
- eventJournalEnabled?: boolean;
1859
- /** Event journal configuration */
1860
- eventJournalConfig?: Partial<Omit<EventJournalServiceConfig, 'pool'>>;
1861
- /** Enable full-text search for specific maps */
1862
- fullTextSearch?: Record<string, FullTextIndexConfig>;
1785
+ /**
1786
+ * SearchCoordinator - Server-side Full-Text Search Handler
1787
+ *
1788
+ * Manages FullTextIndex instances per map and handles search requests.
1789
+ * Part of Phase 11.1a: Server-side BM25 Search.
1790
+ * Phase 11.1b: Live Search Subscriptions with delta updates.
1791
+ * Phase 14.2: Distributed Live Subscriptions support.
1792
+ *
1793
+ * @module search/SearchCoordinator
1794
+ */
1795
+
1796
+ /**
1797
+ * Result item returned from server search.
1798
+ */
1799
+ interface ServerSearchResult {
1800
+ key: string;
1801
+ value: unknown;
1802
+ score: number;
1803
+ matchedTerms: string[];
1863
1804
  }
1864
- declare class ServerCoordinator {
1865
- private httpServer;
1866
- private metricsServer?;
1867
- private metricsService;
1868
- private wss;
1869
- private clients;
1870
- private interceptors;
1871
- private maps;
1872
- private hlc;
1873
- private storage?;
1874
- private jwtSecret;
1875
- private queryRegistry;
1876
- private cluster;
1877
- private partitionService;
1878
- private replicationPipeline?;
1879
- private lockManager;
1880
- private topicManager;
1881
- private securityManager;
1882
- private systemManager;
1883
- private pendingClusterQueries;
1884
- private gcInterval?;
1885
- private heartbeatCheckInterval?;
1886
- private gcReports;
1887
- private mapLoadingPromises;
1888
- private pendingBatchOperations;
1889
- private eventExecutor;
1890
- private backpressure;
1891
- private writeCoalescingEnabled;
1892
- private writeCoalescingOptions;
1893
- private rateLimiter;
1894
- private rateLimitingEnabled;
1895
- private workerPool?;
1896
- private merkleWorker?;
1897
- private crdtMergeWorker?;
1898
- private serializationWorker?;
1899
- private eventPayloadPool;
1900
- private taskletScheduler;
1901
- private writeAckManager;
1902
- private counterHandler;
1903
- private entryProcessorHandler;
1904
- private conflictResolverHandler;
1905
- private eventJournalService?;
1906
- private journalSubscriptions;
1907
- private partitionReassigner?;
1908
- private readReplicaHandler?;
1909
- private merkleTreeManager?;
1910
- private repairScheduler?;
1911
- private searchCoordinator;
1912
- private readonly _nodeId;
1913
- private _actualPort;
1914
- private _actualClusterPort;
1915
- private _readyPromise;
1916
- private _readyResolve;
1917
- constructor(config: ServerCoordinatorConfig);
1805
+ /**
1806
+ * Configuration for enabling search on a map.
1807
+ */
1808
+ interface SearchConfig extends FullTextIndexConfig {
1809
+ }
1810
+ /**
1811
+ * Cached result for a document in a subscription.
1812
+ */
1813
+ interface CachedResult {
1814
+ score: number;
1815
+ matchedTerms: string[];
1816
+ }
1817
+ /**
1818
+ * Represents a live search subscription.
1819
+ */
1820
+ interface SearchSubscription {
1821
+ /** Unique subscription ID */
1822
+ id: string;
1823
+ /** ID of the subscribed client */
1824
+ clientId: string;
1825
+ /** Name of the map being searched */
1826
+ mapName: string;
1827
+ /** Original query string */
1828
+ query: string;
1829
+ /** Tokenized query terms for fast comparison */
1830
+ queryTerms: string[];
1831
+ /** Search options (limit, minScore, boost) */
1832
+ options: SearchOptions;
1833
+ /** Cache of current results for delta computation */
1834
+ currentResults: Map<string, CachedResult>;
1835
+ /** If set, send updates to this coordinator node instead of local client */
1836
+ coordinatorNodeId?: string;
1837
+ /** True if registered via CLUSTER_SUB_REGISTER */
1838
+ isDistributed?: boolean;
1839
+ }
1840
+ /**
1841
+ * Callback type for sending updates to clients.
1842
+ */
1843
+ type SendUpdateCallback = (clientId: string, subscriptionId: string, key: string, value: unknown, score: number, matchedTerms: string[], type: SearchUpdateType) => void;
1844
+ /**
1845
+ * Batched update for a single document change.
1846
+ */
1847
+ interface BatchedUpdate {
1848
+ key: string;
1849
+ value: unknown;
1850
+ score: number;
1851
+ matchedTerms: string[];
1852
+ type: SearchUpdateType;
1853
+ }
1854
+ /**
1855
+ * Callback type for sending batched updates to clients.
1856
+ */
1857
+ type SendBatchUpdateCallback = (clientId: string, subscriptionId: string, updates: BatchedUpdate[]) => void;
1858
+ /**
1859
+ * SearchCoordinator manages full-text search indexes for the server.
1860
+ *
1861
+ * Responsibilities:
1862
+ * - Maintain FullTextIndex per enabled map
1863
+ * - Execute one-shot search queries
1864
+ * - Update indexes when data changes
1865
+ *
1866
+ * @example
1867
+ * ```typescript
1868
+ * const searchCoordinator = new SearchCoordinator();
1869
+ *
1870
+ * // Enable FTS for a map
1871
+ * searchCoordinator.enableSearch('articles', {
1872
+ * fields: ['title', 'body'],
1873
+ * tokenizer: { minLength: 2 },
1874
+ * bm25: { k1: 1.2, b: 0.75 }
1875
+ * });
1876
+ *
1877
+ * // Search
1878
+ * const results = searchCoordinator.search('articles', 'machine learning', {
1879
+ * limit: 20,
1880
+ * boost: { title: 2.0 }
1881
+ * });
1882
+ * ```
1883
+ */
1884
+ declare class SearchCoordinator extends EventEmitter {
1885
+ /** Map name → FullTextIndex */
1886
+ private readonly indexes;
1887
+ /** Map name → FullTextIndexConfig (for reference) */
1888
+ private readonly configs;
1889
+ /** Callback to get document value by key (injected by ServerCoordinator) */
1890
+ private getDocumentValue?;
1891
+ /** Subscription ID → SearchSubscription */
1892
+ private readonly subscriptions;
1893
+ /** Map name → Set of subscription IDs */
1894
+ private readonly subscriptionsByMap;
1895
+ /** Client ID → Set of subscription IDs */
1896
+ private readonly subscriptionsByClient;
1897
+ /** Callback for sending updates to clients */
1898
+ private sendUpdate?;
1899
+ /** Callback for sending batched updates to clients */
1900
+ private sendBatchUpdate?;
1901
+ /** Queue of pending notifications per map */
1902
+ private readonly pendingNotifications;
1903
+ /** Timer for batching notifications */
1904
+ private notificationTimer;
1905
+ /** Batch interval in milliseconds (~1 frame at 60fps) */
1906
+ private readonly BATCH_INTERVAL;
1907
+ /** Node ID for this server (set during init) */
1908
+ private nodeId?;
1909
+ constructor();
1918
1910
  /**
1919
- * Populate FTS indexes from existing map data.
1920
- * Called after storage initialization.
1911
+ * Set the node ID for this server.
1912
+ * Required for distributed subscriptions.
1921
1913
  */
1922
- private backfillSearchIndexes;
1923
- /** Wait for server to be fully ready (ports assigned) */
1924
- ready(): Promise<void>;
1914
+ setNodeId(nodeId: string): void;
1925
1915
  /**
1926
- * Wait for all pending batch operations to complete.
1927
- * Useful for tests that need to verify state after OP_BATCH.
1916
+ * Set the callback for sending updates to clients.
1917
+ * Called by ServerCoordinator during initialization.
1928
1918
  */
1929
- waitForPendingBatches(): Promise<void>;
1930
- /** Get the actual port the server is listening on */
1931
- get port(): number;
1932
- /** Get the actual cluster port */
1933
- get clusterPort(): number;
1934
- /** Get event executor metrics for monitoring */
1935
- getEventExecutorMetrics(): StripeMetrics[];
1936
- /** Get total event executor metrics across all stripes */
1937
- getEventExecutorTotalMetrics(): QueueMetrics;
1938
- /** Get connection rate limiter stats for monitoring */
1939
- getRateLimiterStats(): RateLimiterStats;
1940
- /** Get worker pool stats for monitoring */
1941
- getWorkerPoolStats(): WorkerPoolStats | null;
1942
- /** Check if worker pool is enabled */
1943
- get workerPoolEnabled(): boolean;
1944
- /** Get MerkleWorker for external use (null if worker pool disabled) */
1945
- getMerkleWorker(): MerkleWorker | null;
1946
- /** Get CRDTMergeWorker for external use (null if worker pool disabled) */
1947
- getCRDTMergeWorker(): CRDTMergeWorker | null;
1948
- /** Get SerializationWorker for external use (null if worker pool disabled) */
1949
- getSerializationWorker(): SerializationWorker | null;
1950
- /** Get memory pool stats for monitoring GC pressure reduction */
1951
- getMemoryPoolStats(): {
1952
- eventPayloadPool: ObjectPoolStats;
1919
+ setSendUpdateCallback(callback: SendUpdateCallback): void;
1920
+ /**
1921
+ * Set the callback for sending batched updates to clients.
1922
+ * When set, notifications are batched within BATCH_INTERVAL (16ms) window.
1923
+ * Called by ServerCoordinator during initialization.
1924
+ *
1925
+ * @param callback - Function to call with batched updates
1926
+ */
1927
+ setSendBatchUpdateCallback(callback: SendBatchUpdateCallback): void;
1928
+ /**
1929
+ * Set the callback for retrieving document values.
1930
+ * Called by ServerCoordinator during initialization.
1931
+ */
1932
+ setDocumentValueGetter(getter: (mapName: string, key: string) => unknown | undefined): void;
1933
+ /**
1934
+ * Enable full-text search for a map.
1935
+ *
1936
+ * @param mapName - Name of the map to enable FTS for
1937
+ * @param config - FTS configuration (fields, tokenizer, bm25 options)
1938
+ */
1939
+ enableSearch(mapName: string, config: SearchConfig): void;
1940
+ /**
1941
+ * Disable full-text search for a map.
1942
+ *
1943
+ * @param mapName - Name of the map to disable FTS for
1944
+ */
1945
+ disableSearch(mapName: string): void;
1946
+ /**
1947
+ * Check if FTS is enabled for a map.
1948
+ */
1949
+ isSearchEnabled(mapName: string): boolean;
1950
+ /**
1951
+ * Get enabled map names.
1952
+ */
1953
+ getEnabledMaps(): string[];
1954
+ /**
1955
+ * Execute a one-shot search query.
1956
+ *
1957
+ * @param mapName - Name of the map to search
1958
+ * @param query - Search query text
1959
+ * @param options - Search options (limit, minScore, boost)
1960
+ * @returns Search response payload
1961
+ */
1962
+ search(mapName: string, query: string, options?: FTSSearchOptions): SearchRespPayload;
1963
+ /**
1964
+ * Handle document set/update.
1965
+ * Called by ServerCoordinator when data changes.
1966
+ *
1967
+ * @param mapName - Name of the map
1968
+ * @param key - Document key
1969
+ * @param value - Document value
1970
+ */
1971
+ onDataChange(mapName: string, key: string, value: Record<string, unknown> | null | undefined, changeType: 'add' | 'update' | 'remove'): void;
1972
+ /**
1973
+ * Build index from existing map entries.
1974
+ * Called when FTS is enabled for a map that already has data.
1975
+ *
1976
+ * @param mapName - Name of the map
1977
+ * @param entries - Iterator of [key, value] tuples
1978
+ */
1979
+ buildIndexFromEntries(mapName: string, entries: Iterable<[string, Record<string, unknown> | null]>): void;
1980
+ /**
1981
+ * Get index statistics for monitoring.
1982
+ */
1983
+ getIndexStats(mapName: string): {
1984
+ documentCount: number;
1985
+ fields: string[];
1986
+ } | null;
1987
+ /**
1988
+ * Clear all indexes (for testing or shutdown).
1989
+ */
1990
+ clear(): void;
1991
+ /**
1992
+ * Subscribe to live search results.
1993
+ * Returns initial results and tracks the subscription for delta updates.
1994
+ *
1995
+ * @param clientId - ID of the subscribing client
1996
+ * @param subscriptionId - Unique subscription identifier
1997
+ * @param mapName - Name of the map to search
1998
+ * @param query - Search query text
1999
+ * @param options - Search options (limit, minScore, boost)
2000
+ * @returns Initial search results
2001
+ */
2002
+ subscribe(clientId: string, subscriptionId: string, mapName: string, query: string, options?: SearchOptions): ServerSearchResult[];
2003
+ /**
2004
+ * Unsubscribe from a live search.
2005
+ *
2006
+ * @param subscriptionId - Subscription to remove
2007
+ */
2008
+ unsubscribe(subscriptionId: string): void;
2009
+ /**
2010
+ * Unsubscribe all subscriptions for a client.
2011
+ * Called when a client disconnects.
2012
+ *
2013
+ * @param clientId - ID of the disconnected client
2014
+ */
2015
+ unsubscribeClient(clientId: string): void;
2016
+ /**
2017
+ * Get the number of active subscriptions.
2018
+ */
2019
+ getSubscriptionCount(): number;
2020
+ /**
2021
+ * Register a distributed subscription from a remote coordinator.
2022
+ * Called when receiving CLUSTER_SUB_REGISTER message.
2023
+ *
2024
+ * @param subscriptionId - Unique subscription ID
2025
+ * @param mapName - Map name to search
2026
+ * @param query - Search query string
2027
+ * @param options - Search options
2028
+ * @param coordinatorNodeId - Node ID of the coordinator (receives updates)
2029
+ * @returns Initial search results from this node
2030
+ */
2031
+ registerDistributedSubscription(subscriptionId: string, mapName: string, query: string, options: SearchOptions, coordinatorNodeId: string): {
2032
+ results: ServerSearchResult[];
2033
+ totalHits: number;
1953
2034
  };
1954
- /** Get tasklet scheduler stats for monitoring cooperative multitasking */
1955
- getTaskletSchedulerStats(): TaskletSchedulerStats;
1956
- /** Get tasklet scheduler for scheduling long-running operations */
1957
- getTaskletScheduler(): TaskletScheduler;
1958
2035
  /**
1959
- * Enable full-text search for a map.
1960
- * Can be called at runtime to enable FTS dynamically.
2036
+ * Get a distributed subscription by ID.
2037
+ * Returns undefined if not found or not distributed.
2038
+ */
2039
+ getDistributedSubscription(subscriptionId: string): SearchSubscription | undefined;
2040
+ /**
2041
+ * Unsubscribe all distributed subscriptions where the given node was the coordinator.
2042
+ * Called when a cluster node disconnects.
2043
+ *
2044
+ * @param coordinatorNodeId - Node ID of the disconnected coordinator
2045
+ */
2046
+ unsubscribeByCoordinator(coordinatorNodeId: string): void;
2047
+ /**
2048
+ * Notify subscribers about a document change.
2049
+ * Computes delta (ENTER/UPDATE/LEAVE) for each affected subscription.
2050
+ * For distributed subscriptions, emits 'distributedUpdate' event instead of sending to client.
2051
+ *
2052
+ * @param mapName - Name of the map that changed
2053
+ * @param key - Document key that changed
2054
+ * @param value - New document value (null if removed)
2055
+ * @param changeType - Type of change
2056
+ */
2057
+ private notifySubscribers;
2058
+ /**
2059
+ * Send update to remote coordinator node for a distributed subscription.
2060
+ * Emits 'distributedUpdate' event with ClusterSubUpdatePayload.
1961
2061
  *
1962
- * @param mapName - Name of the map to enable FTS for
1963
- * @param config - FTS configuration (fields, tokenizer, bm25 options)
2062
+ * @param sub - The distributed subscription
2063
+ * @param key - Document key
2064
+ * @param value - Document value
2065
+ * @param score - Search score
2066
+ * @param matchedTerms - Matched search terms
2067
+ * @param changeType - Change type (ENTER/UPDATE/LEAVE)
1964
2068
  */
1965
- enableFullTextSearch(mapName: string, config: FullTextIndexConfig): void;
2069
+ private sendDistributedUpdate;
1966
2070
  /**
1967
- * Disable full-text search for a map.
2071
+ * Score a single document against a subscription's query.
1968
2072
  *
1969
- * @param mapName - Name of the map to disable FTS for
2073
+ * OPTIMIZED: O(Q × D) complexity instead of O(N) full index scan.
2074
+ * Uses pre-tokenized queryTerms and FullTextIndex.scoreSingleDocument().
2075
+ *
2076
+ * @param subscription - The subscription containing query and cached queryTerms
2077
+ * @param key - Document key
2078
+ * @param value - Document value
2079
+ * @param index - The FullTextIndex for this map
2080
+ * @returns Scored result or null if document doesn't match
1970
2081
  */
1971
- disableFullTextSearch(mapName: string): void;
2082
+ private scoreDocument;
1972
2083
  /**
1973
- * Check if full-text search is enabled for a map.
2084
+ * Queue a notification for batched processing.
2085
+ * Notifications are collected and processed together after BATCH_INTERVAL.
1974
2086
  *
1975
- * @param mapName - Name of the map to check
1976
- * @returns True if FTS is enabled
2087
+ * @param mapName - Name of the map that changed
2088
+ * @param key - Document key that changed
2089
+ * @param value - New document value (null if removed)
2090
+ * @param changeType - Type of change
1977
2091
  */
1978
- isFullTextSearchEnabled(mapName: string): boolean;
2092
+ queueNotification(mapName: string, key: string, value: Record<string, unknown> | null, changeType: 'add' | 'update' | 'remove'): void;
1979
2093
  /**
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
2094
+ * Schedule a flush of pending notifications.
2095
+ * Uses setTimeout to batch notifications within BATCH_INTERVAL window.
1984
2096
  */
1985
- getFullTextSearchStats(mapName: string): {
1986
- documentCount: number;
1987
- fields: string[];
1988
- } | null;
2097
+ private scheduleNotificationFlush;
1989
2098
  /**
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
2099
+ * Flush all pending notifications.
2100
+ * Processes each map's notifications and sends batched updates.
1996
2101
  */
1997
- private gracefulClusterDeparture;
2102
+ flushNotifications(): void;
1998
2103
  /**
1999
- * Get list of partition IDs owned by this node
2104
+ * Process batched notifications for a single map.
2105
+ * Computes updates for each subscription and sends as a batch.
2106
+ *
2107
+ * @param mapName - Name of the map
2108
+ * @param notifications - Array of pending notifications
2000
2109
  */
2001
- private getOwnedPartitions;
2110
+ private processBatchedNotifications;
2002
2111
  /**
2003
- * Wait for replication pipeline to flush pending operations
2112
+ * Compute the update for a single document change against a subscription.
2113
+ * Returns null if no update is needed.
2114
+ *
2115
+ * @param subscription - The subscription to check
2116
+ * @param key - Document key
2117
+ * @param value - Document value (null if removed)
2118
+ * @param changeType - Type of change
2119
+ * @param index - The FullTextIndex for this map
2120
+ * @returns BatchedUpdate or null
2004
2121
  */
2005
- private waitForReplicationFlush;
2006
- shutdown(): Promise<void>;
2007
- private handleConnection;
2008
- private handleMessage;
2009
- private updateClientHlc;
2122
+ private computeSubscriptionUpdate;
2123
+ }
2124
+
2125
+ /**
2126
+ * FailureDetector - Phi Accrual Failure Detector
2127
+ *
2128
+ * Implements the Phi Accrual Failure Detection algorithm for distributed systems.
2129
+ * Based on the paper: "The φ Accrual Failure Detector" by Hayashibara et al.
2130
+ *
2131
+ * The detector provides a suspicion level (phi) rather than binary alive/dead status,
2132
+ * allowing the application to make decisions based on configurable thresholds.
2133
+ *
2134
+ * Hazelcast equivalent: com.hazelcast.internal.cluster.fd.PhiAccrualFailureDetector
2135
+ */
2136
+
2137
+ interface FailureDetectorConfig {
2138
+ /** Interval between heartbeat checks (ms). Default: 1000 */
2139
+ heartbeatIntervalMs: number;
2140
+ /** Time after which a node is suspected if no heartbeat received (ms). Default: 5000 */
2141
+ suspicionTimeoutMs: number;
2142
+ /** Time after suspicion before confirming failure (ms). Default: 10000 */
2143
+ confirmationTimeoutMs: number;
2144
+ /** Phi threshold above which a node is considered suspected. Default: 8 */
2145
+ phiThreshold: number;
2146
+ /** Minimum samples required for accurate phi calculation. Default: 10 */
2147
+ minSamples: number;
2148
+ /** Maximum samples to keep in history. Default: 100 */
2149
+ maxSamples: number;
2150
+ /** Initial heartbeat interval estimate (ms). Default: 1000 */
2151
+ initialHeartbeatIntervalMs: number;
2152
+ }
2153
+ declare const DEFAULT_FAILURE_DETECTOR_CONFIG: FailureDetectorConfig;
2154
+ interface NodeState {
2155
+ /** Last heartbeat timestamp */
2156
+ lastHeartbeat: number;
2157
+ /** Heartbeat interval history for phi calculation */
2158
+ intervalHistory: number[];
2159
+ /** Whether node is currently suspected */
2160
+ isSuspected: boolean;
2161
+ /** Timestamp when suspicion started */
2162
+ suspicionStartTime?: number;
2163
+ /** Whether failure has been confirmed */
2164
+ isConfirmedFailed: boolean;
2165
+ }
2166
+ interface FailureDetectorEvents {
2167
+ nodeSuspected: {
2168
+ nodeId: string;
2169
+ phi: number;
2170
+ };
2171
+ nodeRecovered: {
2172
+ nodeId: string;
2173
+ };
2174
+ nodeConfirmedFailed: {
2175
+ nodeId: string;
2176
+ };
2177
+ }
2178
+ declare class FailureDetector extends EventEmitter {
2179
+ private config;
2180
+ private nodeStates;
2181
+ private monitoringNodes;
2182
+ private checkTimer?;
2183
+ private confirmationTimers;
2184
+ private started;
2185
+ constructor(config?: Partial<FailureDetectorConfig>);
2010
2186
  /**
2011
- * Broadcast partition map to all connected and authenticated clients.
2012
- * Called when partition topology changes (node join/leave/failover).
2187
+ * Start the failure detector monitoring loop.
2013
2188
  */
2014
- private broadcastPartitionMap;
2189
+ start(): void;
2015
2190
  /**
2016
- * Notify a client about a merge rejection (Phase 5.05).
2017
- * Finds the client by node ID and sends MERGE_REJECTED message.
2191
+ * Stop the failure detector and clean up.
2018
2192
  */
2019
- private notifyMergeRejection;
2020
- private broadcast;
2193
+ stop(): void;
2021
2194
  /**
2022
- * === OPTIMIZATION 2 & 3: Batched Broadcast with Serialization Caching ===
2023
- * Groups clients by their permission roles and serializes once per group.
2024
- * Also batches multiple events into a single SERVER_BATCH_EVENT message.
2025
- * === OPTIMIZATION 4: Subscription-based Routing ===
2026
- * Only sends events to clients with active subscriptions for affected maps.
2195
+ * Start monitoring a node.
2027
2196
  */
2028
- private broadcastBatch;
2197
+ startMonitoring(nodeId: string): void;
2029
2198
  /**
2030
- * Helper method to get role signature for a client (for caching key)
2199
+ * Stop monitoring a node.
2031
2200
  */
2032
- private getClientRoleSignature;
2201
+ stopMonitoring(nodeId: string): void;
2033
2202
  /**
2034
- * === BACKPRESSURE: Synchronous Broadcast ===
2035
- * Same as broadcastBatch but waits for all sends to complete.
2036
- * Used when backpressure forces sync processing to drain the pipeline.
2203
+ * Record a heartbeat from a node.
2204
+ * This updates the node's state and clears any suspicion.
2037
2205
  */
2038
- private broadcastBatchSync;
2039
- private setupClusterListeners;
2040
- private executeLocalQuery;
2206
+ recordHeartbeat(nodeId: string): void;
2041
2207
  /**
2042
- * Convert server Query format to core Query format for indexed execution.
2043
- * Returns null if conversion is not possible (complex queries).
2208
+ * Check all monitored nodes for failure.
2044
2209
  */
2045
- private convertToCoreQuery;
2210
+ private checkAllNodes;
2046
2211
  /**
2047
- * Convert predicate node to core Query format.
2212
+ * Schedule failure confirmation after suspicion timeout.
2048
2213
  */
2049
- private predicateToCoreQuery;
2214
+ private scheduleConfirmation;
2050
2215
  /**
2051
- * Convert server operator to core query type.
2216
+ * Confirm node failure after confirmation timeout.
2052
2217
  */
2053
- private convertOperator;
2054
- private finalizeClusterQuery;
2218
+ private confirmFailure;
2055
2219
  /**
2056
- * Core operation application logic shared between processLocalOp and processLocalOpForBatch.
2057
- * Handles map merge, storage persistence, query evaluation, and event generation.
2220
+ * Calculate the phi value for a node using the Phi Accrual algorithm.
2058
2221
  *
2059
- * @returns Event payload for broadcasting (or null if operation failed)
2222
+ * Phi = -log10(P_later(t_now - t_last))
2223
+ *
2224
+ * where P_later is the probability that a heartbeat will arrive later than expected.
2060
2225
  */
2061
- private applyOpToMap;
2226
+ calculatePhi(nodeId: string): number;
2062
2227
  /**
2063
- * Broadcast event to cluster members (excluding self).
2228
+ * Calculate mean of an array of numbers.
2064
2229
  */
2065
- private broadcastToCluster;
2230
+ private calculateMean;
2066
2231
  /**
2067
- * Apply replicated operation from another node (callback for ReplicationPipeline)
2068
- * This is called when we receive a replicated operation as a backup node
2232
+ * Calculate variance of an array of numbers.
2069
2233
  */
2070
- private applyReplicatedOperation;
2234
+ private calculateVariance;
2071
2235
  /**
2072
- * Build OpContext for interceptors.
2236
+ * Get list of currently suspected nodes.
2073
2237
  */
2074
- private buildOpContext;
2238
+ getSuspectedNodes(): string[];
2075
2239
  /**
2076
- * Run onBeforeOp interceptors. Returns modified op or null if dropped.
2240
+ * Get list of confirmed failed nodes.
2077
2241
  */
2078
- private runBeforeInterceptors;
2242
+ getConfirmedFailedNodes(): string[];
2079
2243
  /**
2080
- * Run onAfterOp interceptors (fire-and-forget).
2244
+ * Check if a specific node is suspected.
2081
2245
  */
2082
- private runAfterInterceptors;
2083
- private handleLockGranted;
2084
- private processLocalOp;
2246
+ isSuspected(nodeId: string): boolean;
2085
2247
  /**
2086
- * === OPTIMIZATION 1: Async Batch Processing with Backpressure ===
2087
- * Processes validated operations asynchronously after ACK has been sent.
2088
- * Uses BackpressureRegulator to periodically force sync processing and
2089
- * prevent unbounded accumulation of async work.
2248
+ * Check if a specific node's failure is confirmed.
2090
2249
  */
2091
- private processBatchAsync;
2250
+ isConfirmedFailed(nodeId: string): boolean;
2092
2251
  /**
2093
- * === BACKPRESSURE: Synchronous Batch Processing ===
2094
- * Processes operations synchronously, waiting for broadcast completion.
2095
- * Used when backpressure forces sync to drain the pipeline.
2252
+ * Get the current phi value for a node.
2096
2253
  */
2097
- private processBatchSync;
2254
+ getPhi(nodeId: string): number;
2098
2255
  /**
2099
- * Forward operation to owner node and wait for completion.
2100
- * Used in sync processing mode.
2256
+ * Get all monitored nodes.
2101
2257
  */
2102
- private forwardOpAndWait;
2258
+ getMonitoredNodes(): string[];
2259
+ /**
2260
+ * Get metrics for monitoring.
2261
+ */
2262
+ getMetrics(): {
2263
+ monitoredNodes: number;
2264
+ suspectedNodes: number;
2265
+ confirmedFailedNodes: number;
2266
+ };
2267
+ }
2268
+
2269
+ interface ClusterConfig {
2270
+ nodeId: string;
2271
+ host: string;
2272
+ port: number;
2273
+ peers: string[];
2274
+ discovery?: 'manual' | 'kubernetes';
2275
+ serviceName?: string;
2276
+ discoveryInterval?: number;
2277
+ tls?: ClusterTLSConfig;
2278
+ /** Heartbeat interval in milliseconds. Default: 1000 */
2279
+ heartbeatIntervalMs?: number;
2280
+ /** Failure detection configuration */
2281
+ failureDetection?: Partial<FailureDetectorConfig>;
2282
+ }
2283
+ interface ClusterMember {
2284
+ nodeId: string;
2285
+ host: string;
2286
+ port: number;
2287
+ socket: WebSocket;
2288
+ isSelf: boolean;
2289
+ }
2290
+ interface ClusterMessage {
2291
+ 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' | 'CLUSTER_SEARCH_REQ' | 'CLUSTER_SEARCH_RESP' | 'CLUSTER_SEARCH_SUBSCRIBE' | 'CLUSTER_SEARCH_UNSUBSCRIBE' | 'CLUSTER_SEARCH_UPDATE' | 'CLUSTER_SUB_REGISTER' | 'CLUSTER_SUB_ACK' | 'CLUSTER_SUB_UPDATE' | 'CLUSTER_SUB_UNREGISTER';
2292
+ senderId: string;
2293
+ payload: any;
2294
+ }
2295
+ declare class ClusterManager extends EventEmitter {
2296
+ readonly config: ClusterConfig;
2297
+ private server?;
2298
+ private members;
2299
+ private pendingConnections;
2300
+ private reconnectIntervals;
2301
+ private discoveryTimer?;
2302
+ private heartbeatTimer?;
2303
+ private failureDetector;
2304
+ constructor(config: ClusterConfig);
2103
2305
  /**
2104
- * Process a single operation for batch processing.
2105
- * Uses shared applyOpToMap but collects events instead of broadcasting immediately.
2306
+ * Get the failure detector instance.
2106
2307
  */
2107
- private processLocalOpForBatch;
2108
- private handleClusterEvent;
2109
- getMap(name: string, typeHint?: 'LWW' | 'OR'): LWWMap<string, any> | ORMap<string, any>;
2308
+ getFailureDetector(): FailureDetector;
2309
+ private _actualPort;
2310
+ /** Get the actual port the cluster is listening on */
2311
+ get port(): number;
2312
+ start(): Promise<number>;
2313
+ /** Called when server is ready - registers self and initiates peer connections */
2314
+ private onServerReady;
2315
+ stop(): void;
2110
2316
  /**
2111
- * Returns map after ensuring it's fully loaded from storage.
2112
- * Use this for queries to avoid returning empty results during initial load.
2317
+ * Start sending heartbeats to all peers.
2113
2318
  */
2114
- getMapAsync(name: string, typeHint?: 'LWW' | 'OR'): Promise<LWWMap<string, any> | ORMap<string, any>>;
2319
+ private startHeartbeat;
2115
2320
  /**
2116
- * Phase 10.04: Get local record for anti-entropy repair
2117
- * Returns the LWWRecord for a key, used by RepairScheduler
2321
+ * Stop sending heartbeats.
2118
2322
  */
2119
- private getLocalRecord;
2323
+ private stopHeartbeat;
2120
2324
  /**
2121
- * Phase 10.04: Apply repaired record from anti-entropy repair
2122
- * Used by RepairScheduler to apply resolved conflicts
2325
+ * Send heartbeat to all connected peers.
2123
2326
  */
2124
- private applyRepairRecord;
2125
- private loadMapFromStorage;
2126
- private startGarbageCollection;
2327
+ private sendHeartbeatToAll;
2127
2328
  /**
2128
- * Starts the periodic check for dead clients (those that haven't sent PING).
2329
+ * Handle incoming heartbeat from a peer.
2129
2330
  */
2130
- private startHeartbeatCheck;
2331
+ private handleHeartbeat;
2131
2332
  /**
2132
- * Handles incoming PING message from client.
2133
- * Responds with PONG immediately.
2333
+ * Send current member list to a specific node (gossip protocol).
2334
+ * Called when a new node joins to propagate cluster topology.
2134
2335
  */
2135
- private handlePing;
2336
+ private sendMemberList;
2136
2337
  /**
2137
- * Checks if a client is still alive based on heartbeat.
2338
+ * Broadcast member list to all connected nodes.
2339
+ * Called when cluster membership changes.
2138
2340
  */
2139
- isClientAlive(clientId: string): boolean;
2341
+ private broadcastMemberList;
2140
2342
  /**
2141
- * Returns how long the client has been idle (no PING received).
2343
+ * Handle incoming member list from a peer (gossip protocol).
2344
+ * Attempts to connect to unknown members.
2142
2345
  */
2143
- getClientIdleTime(clientId: string): number;
2346
+ private handleMemberList;
2144
2347
  /**
2145
- * Evicts clients that haven't sent a PING within the timeout period.
2348
+ * Handle confirmed node failure.
2146
2349
  */
2147
- private evictDeadClients;
2148
- private reportLocalHlc;
2149
- private handleGcReport;
2150
- private performGarbageCollection;
2151
- private buildTLSOptions;
2350
+ private handleNodeFailure;
2351
+ private connectToPeers;
2352
+ private startDiscovery;
2353
+ private scheduleReconnect;
2354
+ private connectToPeerWithBackoff;
2355
+ private connectToPeer;
2356
+ private _connectToPeerInternal;
2357
+ private handleSocket;
2358
+ send(nodeId: string, type: ClusterMessage['type'], payload: any): void;
2359
+ sendToNode(nodeId: string, message: any): void;
2360
+ getMembers(): string[];
2361
+ isLocal(nodeId: string): boolean;
2362
+ private buildClusterTLSOptions;
2363
+ }
2364
+
2365
+ /**
2366
+ * MigrationManager - Manages gradual partition rebalancing
2367
+ *
2368
+ * Phase 4 Task 03: Parallel Partition Sync
2369
+ *
2370
+ * Features:
2371
+ * - Gradual rebalancing with configurable batch size
2372
+ * - State machine for migration lifecycle
2373
+ * - Backpressure via chunk acknowledgments
2374
+ * - Retry logic for failed migrations
2375
+ * - Metrics and observability
2376
+ */
2377
+
2378
+ declare class MigrationManager extends EventEmitter {
2379
+ private readonly config;
2380
+ private readonly clusterManager;
2381
+ private readonly partitionService;
2382
+ private activeMigrations;
2383
+ private migrationQueue;
2384
+ private incomingMigrations;
2385
+ private pendingChunkAcks;
2386
+ private pendingVerifications;
2387
+ private metrics;
2388
+ private batchTimer;
2389
+ private dataCollector;
2390
+ private dataStorer;
2391
+ constructor(clusterManager: ClusterManager, partitionService: PartitionService, config?: Partial<MigrationConfig>);
2152
2392
  /**
2153
- * Get effective Write Concern level for an operation.
2154
- * Per-op writeConcern overrides batch-level.
2393
+ * Set the data collector callback
2394
+ * Called to collect all records for a partition before migration
2155
2395
  */
2156
- private getEffectiveWriteConcern;
2396
+ setDataCollector(collector: (partitionId: number) => Promise<Uint8Array[]>): void;
2157
2397
  /**
2158
- * Convert string WriteConcern value to enum.
2398
+ * Set the data storer callback
2399
+ * Called to store received records after successful migration
2159
2400
  */
2160
- private stringToWriteConcern;
2401
+ setDataStorer(storer: (partitionId: number, data: Uint8Array[]) => Promise<void>): void;
2161
2402
  /**
2162
- * Process batch with Write Concern tracking.
2163
- * Notifies WriteAckManager at each stage of processing.
2403
+ * Plan migration for topology change
2164
2404
  */
2165
- private processBatchAsyncWithWriteConcern;
2405
+ planMigration(oldDistribution: Map<number, PartitionDistribution>, newDistribution: Map<number, PartitionDistribution>): void;
2166
2406
  /**
2167
- * Synchronous batch processing with Write Concern.
2407
+ * Start batch processing timer
2168
2408
  */
2169
- private processBatchSyncWithWriteConcern;
2409
+ private startBatchProcessing;
2170
2410
  /**
2171
- * Process a single operation with Write Concern level notifications.
2411
+ * Stop batch processing
2172
2412
  */
2173
- private processLocalOpWithWriteConcern;
2413
+ private stopBatchProcessing;
2174
2414
  /**
2175
- * Persist operation synchronously (blocking).
2176
- * Used for PERSISTED Write Concern.
2415
+ * Start next batch of migrations
2177
2416
  */
2178
- private persistOpSync;
2417
+ startNextBatch(): Promise<void>;
2179
2418
  /**
2180
- * Persist operation asynchronously (fire-and-forget).
2181
- * Used for non-PERSISTED Write Concern levels.
2419
+ * Start migration for a single partition
2182
2420
  */
2183
- private persistOpAsync;
2184
- }
2185
-
2186
- interface PostgresAdapterOptions {
2187
- tableName?: string;
2188
- }
2189
- declare class PostgresAdapter implements IServerStorage {
2190
- private pool;
2191
- private tableName;
2192
- constructor(configOrPool: PoolConfig | Pool, options?: PostgresAdapterOptions);
2193
- initialize(): Promise<void>;
2194
- close(): Promise<void>;
2195
- load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
2196
- loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
2197
- loadAllKeys(mapName: string): Promise<string[]>;
2198
- store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
2199
- storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
2200
- delete(mapName: string, key: string): Promise<void>;
2201
- deleteAll(mapName: string, keys: string[]): Promise<void>;
2202
- private mapRowToRecord;
2203
- private isORMapValue;
2204
- }
2205
-
2206
- /**
2207
- * In-memory implementation of IServerStorage.
2208
- * Useful for development, testing, and demos without requiring a database.
2209
- *
2210
- * Note: Data is lost when the server restarts.
2211
- */
2212
- declare class MemoryServerAdapter implements IServerStorage {
2213
- private storage;
2214
- initialize(): Promise<void>;
2215
- close(): Promise<void>;
2216
- private getMap;
2217
- load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
2218
- loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
2219
- loadAllKeys(mapName: string): Promise<string[]>;
2220
- store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
2221
- storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
2222
- delete(mapName: string, key: string): Promise<void>;
2223
- deleteAll(mapName: string, keys: string[]): Promise<void>;
2224
- }
2225
-
2226
- declare class SecurityManager {
2227
- private policies;
2228
- constructor(policies?: PermissionPolicy[]);
2229
- addPolicy(policy: PermissionPolicy): void;
2230
- checkPermission(principal: Principal, mapName: string, action: PermissionType): boolean;
2231
- filterObject(object: any, principal: Principal, mapName: string): any;
2232
- private hasRole;
2233
- private matchesMap;
2234
- }
2235
-
2236
- declare const logger: pino.Logger<never, boolean>;
2237
- type Logger = typeof logger;
2238
-
2239
- /**
2240
- * ConnectionRateLimiter - Rate limiter for incoming WebSocket connections.
2241
- *
2242
- * Implements connection rate limiting to prevent connection storms and
2243
- * protect the server from being overwhelmed during high load scenarios.
2244
- *
2245
- * Features:
2246
- * - Limits connections per second to prevent TCP backlog exhaustion
2247
- * - Tracks pending connections (in-progress handshakes)
2248
- * - Provides graceful rejection when limits are exceeded
2249
- * - Auto-resets counters after cooldown period
2250
- */
2251
- interface RateLimiterConfig {
2252
- /** Maximum new connections allowed per second (default: 100) */
2253
- maxConnectionsPerSecond: number;
2254
- /** Maximum pending connections waiting for handshake (default: 1000) */
2255
- maxPendingConnections: number;
2256
- /** Cooldown period in ms after which counters reset (default: 1000) */
2257
- cooldownMs: number;
2258
- }
2259
- interface RateLimiterStats {
2260
- /** Current connections per second rate */
2261
- connectionsPerSecond: number;
2262
- /** Number of connections currently pending (handshake in progress) */
2263
- pendingConnections: number;
2264
- /** Total connections established since start */
2265
- totalConnections: number;
2266
- /** Total connections rejected due to rate limiting */
2267
- totalRejected: number;
2268
- }
2269
- declare class ConnectionRateLimiter {
2270
- private config;
2271
- /** Connection attempts in current window */
2272
- private connectionCount;
2273
- /** Timestamp when current window started */
2274
- private windowStart;
2275
- /** Currently pending connections (handshake in progress) */
2276
- private pendingCount;
2277
- /** Total connections established since start */
2278
- private totalConnections;
2279
- /** Total connections rejected since start */
2280
- private totalRejected;
2281
- constructor(config?: Partial<RateLimiterConfig>);
2421
+ private startPartitionMigration;
2282
2422
  /**
2283
- * Check if a new connection should be accepted.
2284
- * @returns true if the connection should be accepted, false if it should be rejected
2423
+ * Split records into chunks
2285
2424
  */
2286
- shouldAccept(): boolean;
2425
+ private chunkify;
2287
2426
  /**
2288
- * Register a connection attempt.
2289
- * Call this when a new connection is initiated (before handshake completes).
2427
+ * Calculate checksum for a chunk using native xxhash
2290
2428
  */
2291
- onConnectionAttempt(): void;
2429
+ private calculateChecksum;
2292
2430
  /**
2293
- * Register that a connection has been established (handshake complete).
2294
- * Call this when the connection is fully established and authenticated.
2431
+ * Calculate checksum for all partition records using streaming xxhash
2295
2432
  */
2296
- onConnectionEstablished(): void;
2433
+ private calculatePartitionChecksum;
2297
2434
  /**
2298
- * Register that a connection has been closed.
2299
- * Call this when a pending connection is closed before completing handshake.
2435
+ * Wait for chunk acknowledgment
2300
2436
  */
2301
- onConnectionClosed(): void;
2437
+ private waitForChunkAck;
2302
2438
  /**
2303
- * Register that a connection was rejected.
2304
- * Call this when shouldAccept() returns false and the connection is rejected.
2439
+ * Wait for migration verification
2305
2440
  */
2306
- onConnectionRejected(): void;
2441
+ private waitForVerification;
2307
2442
  /**
2308
- * Decrease pending count when a connection times out or fails.
2309
- * Call this when a pending connection fails to complete handshake.
2443
+ * Handle successful migration completion
2310
2444
  */
2311
- onPendingConnectionFailed(): void;
2445
+ private onMigrationComplete;
2312
2446
  /**
2313
- * Get current rate limiter statistics.
2447
+ * Handle migration failure
2314
2448
  */
2315
- getStats(): RateLimiterStats;
2449
+ private onMigrationFailed;
2316
2450
  /**
2317
- * Reset the rate limiter state.
2318
- * Useful for testing or when recovering from errors.
2451
+ * Handle MIGRATION_START message
2319
2452
  */
2320
- reset(): void;
2453
+ private handleMigrationStart;
2321
2454
  /**
2322
- * Update configuration at runtime.
2455
+ * Handle MIGRATION_CHUNK message
2323
2456
  */
2324
- updateConfig(config: Partial<RateLimiterConfig>): void;
2457
+ private handleMigrationChunk;
2325
2458
  /**
2326
- * Check if window has expired and reset if needed.
2459
+ * Handle MIGRATION_COMPLETE message
2327
2460
  */
2328
- private maybeResetWindow;
2329
- }
2330
-
2331
- declare class TimestampInterceptor implements IInterceptor {
2332
- name: string;
2333
- onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp>;
2334
- }
2335
-
2336
- interface RateLimitConfig {
2337
- windowMs: number;
2338
- maxOps: number;
2339
- }
2340
- declare class RateLimitInterceptor implements IInterceptor {
2341
- name: string;
2342
- private limits;
2343
- private config;
2344
- constructor(config?: RateLimitConfig);
2345
- onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
2346
- onDisconnect(context: any): Promise<void>;
2347
- }
2348
-
2349
- /**
2350
- * Native Module Statistics
2351
- *
2352
- * Provides information about available native optimizations.
2353
- *
2354
- * Phase 3.05: Integration
2355
- */
2356
-
2357
- /**
2358
- * Native module availability status
2359
- */
2360
- interface NativeModuleStatus {
2361
- /** Native xxHash64 is available and being used */
2362
- nativeHash: boolean;
2363
- /** SharedArrayBuffer is available */
2364
- sharedArrayBuffer: boolean;
2365
- }
2366
- /**
2367
- * Comprehensive native statistics
2368
- */
2369
- interface NativeStats {
2370
- /** Module availability status */
2371
- modules: NativeModuleStatus;
2372
- /** Shared memory statistics (if enabled) */
2373
- sharedMemory: SharedMemoryStats | null;
2374
- /** Summary of what's being used */
2375
- summary: string;
2376
- }
2377
- /**
2378
- * Check which native modules are available.
2379
- */
2380
- declare function getNativeModuleStatus(): NativeModuleStatus;
2381
- /**
2382
- * Get native statistics including shared memory.
2383
- *
2384
- * @param sharedMemoryManager - Optional SharedMemoryManager instance
2385
- */
2386
- declare function getNativeStats(sharedMemoryManager?: SharedMemoryManager): NativeStats;
2387
- /**
2388
- * Log native module status to console.
2389
- */
2390
- declare function logNativeStatus(): void;
2391
-
2392
- /**
2393
- * FailureDetector - Phi Accrual Failure Detector
2394
- *
2395
- * Implements the Phi Accrual Failure Detection algorithm for distributed systems.
2396
- * Based on the paper: "The φ Accrual Failure Detector" by Hayashibara et al.
2397
- *
2398
- * The detector provides a suspicion level (phi) rather than binary alive/dead status,
2399
- * allowing the application to make decisions based on configurable thresholds.
2400
- *
2401
- * Hazelcast equivalent: com.hazelcast.internal.cluster.fd.PhiAccrualFailureDetector
2402
- */
2403
-
2404
- interface FailureDetectorConfig {
2405
- /** Interval between heartbeat checks (ms). Default: 1000 */
2406
- heartbeatIntervalMs: number;
2407
- /** Time after which a node is suspected if no heartbeat received (ms). Default: 5000 */
2408
- suspicionTimeoutMs: number;
2409
- /** Time after suspicion before confirming failure (ms). Default: 10000 */
2410
- confirmationTimeoutMs: number;
2411
- /** Phi threshold above which a node is considered suspected. Default: 8 */
2412
- phiThreshold: number;
2413
- /** Minimum samples required for accurate phi calculation. Default: 10 */
2414
- minSamples: number;
2415
- /** Maximum samples to keep in history. Default: 100 */
2416
- maxSamples: number;
2417
- /** Initial heartbeat interval estimate (ms). Default: 1000 */
2418
- initialHeartbeatIntervalMs: number;
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
- }
2445
- declare class FailureDetector extends EventEmitter {
2446
- private config;
2447
- private nodeStates;
2448
- private monitoringNodes;
2449
- private checkTimer?;
2450
- private confirmationTimers;
2451
- private started;
2452
- constructor(config?: Partial<FailureDetectorConfig>);
2461
+ private handleMigrationComplete;
2453
2462
  /**
2454
- * Start the failure detector monitoring loop.
2463
+ * Handle MIGRATION_CHUNK_ACK message
2455
2464
  */
2456
- start(): void;
2465
+ private handleMigrationChunkAck;
2457
2466
  /**
2458
- * Stop the failure detector and clean up.
2467
+ * Handle MIGRATION_VERIFY message
2459
2468
  */
2460
- stop(): void;
2469
+ private handleMigrationVerify;
2461
2470
  /**
2462
- * Start monitoring a node.
2471
+ * Reassemble chunks into continuous data
2463
2472
  */
2464
- startMonitoring(nodeId: string): void;
2473
+ private reassemble;
2465
2474
  /**
2466
- * Stop monitoring a node.
2475
+ * Deserialize records from chunk data
2467
2476
  */
2468
- stopMonitoring(nodeId: string): void;
2477
+ private deserializeRecords;
2469
2478
  /**
2470
- * Record a heartbeat from a node.
2471
- * This updates the node's state and clears any suspicion.
2479
+ * Setup cluster message handlers
2472
2480
  */
2473
- recordHeartbeat(nodeId: string): void;
2481
+ private setupMessageHandlers;
2474
2482
  /**
2475
- * Check all monitored nodes for failure.
2483
+ * Check if a partition is currently migrating
2476
2484
  */
2477
- private checkAllNodes;
2485
+ isActive(partitionId: number): boolean;
2486
+ /**
2487
+ * Get migration status
2488
+ */
2489
+ getStatus(): MigrationStatus;
2490
+ /**
2491
+ * Get migration metrics
2492
+ */
2493
+ getMetrics(): MigrationMetrics;
2494
+ /**
2495
+ * Cancel all active and queued migrations
2496
+ */
2497
+ cancelAll(): Promise<void>;
2498
+ /**
2499
+ * Cleanup resources (sync version for backwards compatibility)
2500
+ */
2501
+ close(): void;
2502
+ /**
2503
+ * Async cleanup - waits for cancellation to complete
2504
+ */
2505
+ closeAsync(): Promise<void>;
2506
+ }
2507
+
2508
+ interface PartitionDistribution {
2509
+ owner: string;
2510
+ backups: string[];
2511
+ }
2512
+ interface PartitionServiceEvents {
2513
+ 'rebalanced': (map: PartitionMap, changes: PartitionChange[]) => void;
2514
+ 'partitionMoved': (info: {
2515
+ partitionId: number;
2516
+ previousOwner: string;
2517
+ newOwner: string;
2518
+ version: number;
2519
+ }) => void;
2520
+ }
2521
+ interface PartitionServiceConfig {
2522
+ /** Enable gradual rebalancing (default: false for backward compatibility) */
2523
+ gradualRebalancing: boolean;
2524
+ /** Migration configuration */
2525
+ migration: Partial<MigrationConfig>;
2526
+ }
2527
+ declare class PartitionService extends EventEmitter {
2528
+ private cluster;
2529
+ private partitions;
2530
+ private readonly PARTITION_COUNT;
2531
+ private readonly BACKUP_COUNT;
2532
+ private mapVersion;
2533
+ private lastRebalanceTime;
2534
+ private config;
2535
+ private migrationManager;
2536
+ constructor(cluster: ClusterManager, config?: Partial<PartitionServiceConfig>);
2537
+ /**
2538
+ * Handle membership change
2539
+ */
2540
+ private onMembershipChange;
2541
+ getPartitionId(key: string): number;
2542
+ getDistribution(key: string): PartitionDistribution;
2543
+ getOwner(key: string): string;
2544
+ isLocalOwner(key: string): boolean;
2545
+ isLocalBackup(key: string): boolean;
2546
+ isRelated(key: string): boolean;
2478
2547
  /**
2479
- * Schedule failure confirmation after suspicion timeout.
2548
+ * Get current partition map version
2480
2549
  */
2481
- private scheduleConfirmation;
2550
+ getMapVersion(): number;
2482
2551
  /**
2483
- * Confirm node failure after confirmation timeout.
2552
+ * Generate full PartitionMap for client consumption
2484
2553
  */
2485
- private confirmFailure;
2554
+ getPartitionMap(): PartitionMap;
2486
2555
  /**
2487
- * Calculate the phi value for a node using the Phi Accrual algorithm.
2488
- *
2489
- * Phi = -log10(P_later(t_now - t_last))
2490
- *
2491
- * where P_later is the probability that a heartbeat will arrive later than expected.
2556
+ * Get partition info by ID
2492
2557
  */
2493
- calculatePhi(nodeId: string): number;
2558
+ getPartitionInfo(partitionId: number): PartitionInfo | null;
2494
2559
  /**
2495
- * Calculate mean of an array of numbers.
2560
+ * Get owner node for a partition ID
2496
2561
  */
2497
- private calculateMean;
2562
+ getPartitionOwner(partitionId: number): string | null;
2563
+ private rebalance;
2498
2564
  /**
2499
- * Calculate variance of an array of numbers.
2565
+ * Perform gradual rebalancing using MigrationManager
2500
2566
  */
2501
- private calculateVariance;
2567
+ private rebalanceGradual;
2502
2568
  /**
2503
- * Get list of currently suspected nodes.
2569
+ * Set partition owner (called after migration completes)
2504
2570
  */
2505
- getSuspectedNodes(): string[];
2571
+ setOwner(partitionId: number, nodeId: string): void;
2506
2572
  /**
2507
- * Get list of confirmed failed nodes.
2573
+ * Get backups for a partition
2508
2574
  */
2509
- getConfirmedFailedNodes(): string[];
2575
+ getBackups(partitionId: number): string[];
2510
2576
  /**
2511
- * Check if a specific node is suspected.
2577
+ * Get migration status
2512
2578
  */
2513
- isSuspected(nodeId: string): boolean;
2579
+ getMigrationStatus(): MigrationStatus | null;
2514
2580
  /**
2515
- * Check if a specific node's failure is confirmed.
2581
+ * Check if partition is currently migrating
2516
2582
  */
2517
- isConfirmedFailed(nodeId: string): boolean;
2583
+ isMigrating(partitionId: number): boolean;
2518
2584
  /**
2519
- * Get the current phi value for a node.
2585
+ * Check if any partition is currently migrating
2520
2586
  */
2521
- getPhi(nodeId: string): number;
2587
+ isRebalancing(): boolean;
2522
2588
  /**
2523
- * Get all monitored nodes.
2589
+ * Get MigrationManager for configuration
2524
2590
  */
2525
- getMonitoredNodes(): string[];
2591
+ getMigrationManager(): MigrationManager | null;
2526
2592
  /**
2527
- * Get metrics for monitoring.
2593
+ * Cancel all migrations
2528
2594
  */
2529
- getMetrics(): {
2530
- monitoredNodes: number;
2531
- suspectedNodes: number;
2532
- confirmedFailedNodes: number;
2533
- };
2595
+ cancelMigrations(): Promise<void>;
2534
2596
  }
2535
2597
 
2536
- interface ClusterConfig {
2537
- nodeId: string;
2538
- host: string;
2598
+ /**
2599
+ * ClusterSearchCoordinator - Distributed Search across Cluster Nodes
2600
+ *
2601
+ * Implements Scatter-Gather architecture for distributed full-text search.
2602
+ * Broadcasts search queries to all nodes, collects local results, and merges
2603
+ * them using Reciprocal Rank Fusion (RRF) for unified ranking.
2604
+ *
2605
+ * Key features:
2606
+ * - Scatter-Gather search across all cluster nodes
2607
+ * - RRF-based result merging (handles distributed IDF problem)
2608
+ * - Cursor-based pagination for efficient deep results
2609
+ * - Graceful degradation on node failures
2610
+ * - Single-node optimization (skip broadcast when all data is local)
2611
+ *
2612
+ * @module search/ClusterSearchCoordinator
2613
+ */
2614
+
2615
+ /**
2616
+ * Configuration for ClusterSearchCoordinator.
2617
+ */
2618
+ interface ClusterSearchConfig {
2619
+ /** RRF constant k (default: 60) */
2620
+ rrfK?: number;
2621
+ /** Default timeout for node responses (ms) */
2622
+ defaultTimeoutMs?: number;
2623
+ /** Minimum nodes required to respond (default: 0 = all available) */
2624
+ defaultMinResponses?: number;
2625
+ }
2626
+
2627
+ interface ServerCoordinatorConfig {
2539
2628
  port: number;
2540
- peers: string[];
2629
+ nodeId: string;
2630
+ storage?: IServerStorage;
2631
+ jwtSecret?: string;
2632
+ host?: string;
2633
+ clusterPort?: number;
2634
+ peers?: string[];
2635
+ securityPolicies?: PermissionPolicy[];
2636
+ /** Callback to resolve dynamic peer addresses after ports are known */
2637
+ resolvePeers?: () => string[];
2638
+ interceptors?: IInterceptor[];
2639
+ metricsPort?: number;
2541
2640
  discovery?: 'manual' | 'kubernetes';
2542
2641
  serviceName?: string;
2543
2642
  discoveryInterval?: number;
2544
- tls?: ClusterTLSConfig;
2545
- /** Heartbeat interval in milliseconds. Default: 1000 */
2546
- heartbeatIntervalMs?: number;
2547
- /** Failure detection configuration */
2548
- failureDetection?: Partial<FailureDetectorConfig>;
2549
- }
2550
- interface ClusterMember {
2551
- nodeId: string;
2552
- host: string;
2553
- port: number;
2554
- socket: WebSocket;
2555
- isSelf: boolean;
2556
- }
2557
- interface ClusterMessage {
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';
2559
- senderId: string;
2560
- payload: any;
2643
+ tls?: TLSConfig;
2644
+ clusterTls?: ClusterTLSConfig;
2645
+ /** Total event queue capacity for bounded queue (default: 10000) */
2646
+ eventQueueCapacity?: number;
2647
+ /** Number of event queue stripes for parallel processing (default: 4) */
2648
+ eventStripeCount?: number;
2649
+ /** Enable/disable backpressure (default: true) */
2650
+ backpressureEnabled?: boolean;
2651
+ /** How often to force sync processing (default: 100 operations) */
2652
+ backpressureSyncFrequency?: number;
2653
+ /** Maximum pending async operations before blocking (default: 1000) */
2654
+ backpressureMaxPending?: number;
2655
+ /** Backoff timeout in ms when at capacity (default: 5000) */
2656
+ backpressureBackoffMs?: number;
2657
+ /** Enable/disable write coalescing (default: true) */
2658
+ writeCoalescingEnabled?: boolean;
2659
+ /** Coalescing preset: 'conservative', 'balanced', 'highThroughput', 'aggressive' (default: 'highThroughput') */
2660
+ writeCoalescingPreset?: CoalescingPreset;
2661
+ /** Maximum messages to batch before forcing flush (default: 500 for highThroughput) */
2662
+ writeCoalescingMaxBatch?: number;
2663
+ /** Maximum delay before flushing in ms (default: 10 for highThroughput) */
2664
+ writeCoalescingMaxDelayMs?: number;
2665
+ /** Maximum batch size in bytes (default: 262144/256KB for highThroughput) */
2666
+ writeCoalescingMaxBytes?: number;
2667
+ /** WebSocket backlog for pending connections (default: 511) */
2668
+ wsBacklog?: number;
2669
+ /** Enable WebSocket per-message compression (default: false for CPU savings) */
2670
+ wsCompression?: boolean;
2671
+ /** Maximum WebSocket payload size in bytes (default: 64MB) */
2672
+ wsMaxPayload?: number;
2673
+ /** Maximum server connections (default: 10000) */
2674
+ maxConnections?: number;
2675
+ /** Server timeout in ms (default: 120000 = 2 min) */
2676
+ serverTimeout?: number;
2677
+ /** Keep-alive timeout in ms (default: 5000) */
2678
+ keepAliveTimeout?: number;
2679
+ /** Headers timeout in ms (default: 60000) */
2680
+ headersTimeout?: number;
2681
+ /** Enable connection rate limiting (default: true) */
2682
+ rateLimitingEnabled?: boolean;
2683
+ /** Maximum new connections per second (default: 100) */
2684
+ maxConnectionsPerSecond?: number;
2685
+ /** Maximum pending connections (default: 1000) */
2686
+ maxPendingConnections?: number;
2687
+ /** Enable worker pool for CPU-bound operations (default: false) */
2688
+ workerPoolEnabled?: boolean;
2689
+ /** Worker pool configuration */
2690
+ workerPoolConfig?: Partial<WorkerPoolConfig>;
2691
+ /** Default timeout for Write Concern acknowledgments in ms (default: 5000) */
2692
+ writeAckTimeout?: number;
2693
+ /** Enable replication to backup nodes (default: true when cluster has peers) */
2694
+ replicationEnabled?: boolean;
2695
+ /** Default consistency level for replication (default: EVENTUAL) */
2696
+ defaultConsistency?: ConsistencyLevel;
2697
+ /** Replication configuration */
2698
+ replicationConfig?: Partial<ReplicationConfig>;
2699
+ /** Enable event journal for audit/CDC (default: false) */
2700
+ eventJournalEnabled?: boolean;
2701
+ /** Event journal configuration */
2702
+ eventJournalConfig?: Partial<Omit<EventJournalServiceConfig, 'pool'>>;
2703
+ /** Enable full-text search for specific maps */
2704
+ fullTextSearch?: Record<string, FullTextIndexConfig>;
2705
+ /** Configuration for distributed search across cluster nodes */
2706
+ distributedSearch?: ClusterSearchConfig;
2561
2707
  }
2562
- declare class ClusterManager extends EventEmitter {
2563
- readonly config: ClusterConfig;
2564
- private server?;
2565
- private members;
2566
- private pendingConnections;
2567
- private reconnectIntervals;
2568
- private discoveryTimer?;
2569
- private heartbeatTimer?;
2570
- private failureDetector;
2571
- constructor(config: ClusterConfig);
2708
+ declare class ServerCoordinator {
2709
+ private httpServer;
2710
+ private metricsServer?;
2711
+ private metricsService;
2712
+ private wss;
2713
+ private clients;
2714
+ private interceptors;
2715
+ private maps;
2716
+ private hlc;
2717
+ private storage?;
2718
+ private jwtSecret;
2719
+ private queryRegistry;
2720
+ private cluster;
2721
+ private partitionService;
2722
+ private replicationPipeline?;
2723
+ private lockManager;
2724
+ private topicManager;
2725
+ private securityManager;
2726
+ private systemManager;
2727
+ private pendingClusterQueries;
2728
+ private gcInterval?;
2729
+ private heartbeatCheckInterval?;
2730
+ private gcReports;
2731
+ private mapLoadingPromises;
2732
+ private pendingBatchOperations;
2733
+ private eventExecutor;
2734
+ private backpressure;
2735
+ private writeCoalescingEnabled;
2736
+ private writeCoalescingOptions;
2737
+ private rateLimiter;
2738
+ private rateLimitingEnabled;
2739
+ private workerPool?;
2740
+ private merkleWorker?;
2741
+ private crdtMergeWorker?;
2742
+ private serializationWorker?;
2743
+ private eventPayloadPool;
2744
+ private taskletScheduler;
2745
+ private writeAckManager;
2746
+ private counterHandler;
2747
+ private entryProcessorHandler;
2748
+ private conflictResolverHandler;
2749
+ private eventJournalService?;
2750
+ private journalSubscriptions;
2751
+ private partitionReassigner?;
2752
+ private readReplicaHandler?;
2753
+ private merkleTreeManager?;
2754
+ private repairScheduler?;
2755
+ private searchCoordinator;
2756
+ private clusterSearchCoordinator?;
2757
+ private distributedSubCoordinator?;
2758
+ private readonly _nodeId;
2759
+ private _actualPort;
2760
+ private _actualClusterPort;
2761
+ private _readyPromise;
2762
+ private _readyResolve;
2763
+ constructor(config: ServerCoordinatorConfig);
2764
+ /**
2765
+ * Populate FTS indexes from existing map data.
2766
+ * Called after storage initialization.
2767
+ */
2768
+ private backfillSearchIndexes;
2769
+ /** Wait for server to be fully ready (ports assigned) */
2770
+ ready(): Promise<void>;
2771
+ /**
2772
+ * Wait for all pending batch operations to complete.
2773
+ * Useful for tests that need to verify state after OP_BATCH.
2774
+ */
2775
+ waitForPendingBatches(): Promise<void>;
2776
+ /** Get the actual port the server is listening on */
2777
+ get port(): number;
2778
+ /** Get the actual cluster port */
2779
+ get clusterPort(): number;
2780
+ /** Get event executor metrics for monitoring */
2781
+ getEventExecutorMetrics(): StripeMetrics[];
2782
+ /** Get total event executor metrics across all stripes */
2783
+ getEventExecutorTotalMetrics(): QueueMetrics;
2784
+ /** Get connection rate limiter stats for monitoring */
2785
+ getRateLimiterStats(): RateLimiterStats;
2786
+ /** Get worker pool stats for monitoring */
2787
+ getWorkerPoolStats(): WorkerPoolStats | null;
2788
+ /** Check if worker pool is enabled */
2789
+ get workerPoolEnabled(): boolean;
2790
+ /** Get MerkleWorker for external use (null if worker pool disabled) */
2791
+ getMerkleWorker(): MerkleWorker | null;
2792
+ /** Get CRDTMergeWorker for external use (null if worker pool disabled) */
2793
+ getCRDTMergeWorker(): CRDTMergeWorker | null;
2794
+ /** Get SerializationWorker for external use (null if worker pool disabled) */
2795
+ getSerializationWorker(): SerializationWorker | null;
2796
+ /** Get memory pool stats for monitoring GC pressure reduction */
2797
+ getMemoryPoolStats(): {
2798
+ eventPayloadPool: ObjectPoolStats;
2799
+ };
2800
+ /** Get tasklet scheduler stats for monitoring cooperative multitasking */
2801
+ getTaskletSchedulerStats(): TaskletSchedulerStats;
2802
+ /** Get tasklet scheduler for scheduling long-running operations */
2803
+ getTaskletScheduler(): TaskletScheduler;
2572
2804
  /**
2573
- * Get the failure detector instance.
2805
+ * Enable full-text search for a map.
2806
+ * Can be called at runtime to enable FTS dynamically.
2807
+ *
2808
+ * @param mapName - Name of the map to enable FTS for
2809
+ * @param config - FTS configuration (fields, tokenizer, bm25 options)
2574
2810
  */
2575
- getFailureDetector(): FailureDetector;
2576
- private _actualPort;
2577
- /** Get the actual port the cluster is listening on */
2578
- get port(): number;
2579
- start(): Promise<number>;
2580
- /** Called when server is ready - registers self and initiates peer connections */
2581
- private onServerReady;
2582
- stop(): void;
2811
+ enableFullTextSearch(mapName: string, config: FullTextIndexConfig): void;
2583
2812
  /**
2584
- * Start sending heartbeats to all peers.
2813
+ * Disable full-text search for a map.
2814
+ *
2815
+ * @param mapName - Name of the map to disable FTS for
2585
2816
  */
2586
- private startHeartbeat;
2817
+ disableFullTextSearch(mapName: string): void;
2587
2818
  /**
2588
- * Stop sending heartbeats.
2819
+ * Check if full-text search is enabled for a map.
2820
+ *
2821
+ * @param mapName - Name of the map to check
2822
+ * @returns True if FTS is enabled
2589
2823
  */
2590
- private stopHeartbeat;
2824
+ isFullTextSearchEnabled(mapName: string): boolean;
2591
2825
  /**
2592
- * Send heartbeat to all connected peers.
2826
+ * Get FTS index statistics for a map.
2827
+ *
2828
+ * @param mapName - Name of the map
2829
+ * @returns Index stats or null if FTS not enabled
2593
2830
  */
2594
- private sendHeartbeatToAll;
2831
+ getFullTextSearchStats(mapName: string): {
2832
+ documentCount: number;
2833
+ fields: string[];
2834
+ } | null;
2595
2835
  /**
2596
- * Handle incoming heartbeat from a peer.
2836
+ * Phase 10.02: Graceful cluster departure
2837
+ *
2838
+ * Notifies the cluster that this node is leaving and allows time for:
2839
+ * 1. Pending replication to complete
2840
+ * 2. Other nodes to detect departure
2841
+ * 3. Partition reassignment to begin
2597
2842
  */
2598
- private handleHeartbeat;
2843
+ private gracefulClusterDeparture;
2599
2844
  /**
2600
- * Send current member list to a specific node (gossip protocol).
2601
- * Called when a new node joins to propagate cluster topology.
2845
+ * Get list of partition IDs owned by this node
2602
2846
  */
2603
- private sendMemberList;
2847
+ private getOwnedPartitions;
2604
2848
  /**
2605
- * Broadcast member list to all connected nodes.
2606
- * Called when cluster membership changes.
2849
+ * Wait for replication pipeline to flush pending operations
2607
2850
  */
2608
- private broadcastMemberList;
2851
+ private waitForReplicationFlush;
2852
+ shutdown(): Promise<void>;
2853
+ private handleConnection;
2854
+ private handleMessage;
2855
+ private updateClientHlc;
2609
2856
  /**
2610
- * Handle incoming member list from a peer (gossip protocol).
2611
- * Attempts to connect to unknown members.
2857
+ * Broadcast partition map to all connected and authenticated clients.
2858
+ * Called when partition topology changes (node join/leave/failover).
2612
2859
  */
2613
- private handleMemberList;
2860
+ private broadcastPartitionMap;
2614
2861
  /**
2615
- * Handle confirmed node failure.
2862
+ * Notify a client about a merge rejection (Phase 5.05).
2863
+ * Finds the client by node ID and sends MERGE_REJECTED message.
2616
2864
  */
2617
- private handleNodeFailure;
2618
- private connectToPeers;
2619
- private startDiscovery;
2620
- private scheduleReconnect;
2621
- private connectToPeerWithBackoff;
2622
- private connectToPeer;
2623
- private _connectToPeerInternal;
2624
- private handleSocket;
2625
- send(nodeId: string, type: ClusterMessage['type'], payload: any): void;
2626
- sendToNode(nodeId: string, message: any): void;
2627
- getMembers(): string[];
2628
- isLocal(nodeId: string): boolean;
2629
- private buildClusterTLSOptions;
2630
- }
2631
-
2632
- /**
2633
- * MigrationManager - Manages gradual partition rebalancing
2634
- *
2635
- * Phase 4 Task 03: Parallel Partition Sync
2636
- *
2637
- * Features:
2638
- * - Gradual rebalancing with configurable batch size
2639
- * - State machine for migration lifecycle
2640
- * - Backpressure via chunk acknowledgments
2641
- * - Retry logic for failed migrations
2642
- * - Metrics and observability
2643
- */
2644
-
2645
- declare class MigrationManager extends EventEmitter {
2646
- private readonly config;
2647
- private readonly clusterManager;
2648
- private readonly partitionService;
2649
- private activeMigrations;
2650
- private migrationQueue;
2651
- private incomingMigrations;
2652
- private pendingChunkAcks;
2653
- private pendingVerifications;
2654
- private metrics;
2655
- private batchTimer;
2656
- private dataCollector;
2657
- private dataStorer;
2658
- constructor(clusterManager: ClusterManager, partitionService: PartitionService, config?: Partial<MigrationConfig>);
2865
+ private notifyMergeRejection;
2866
+ private broadcast;
2659
2867
  /**
2660
- * Set the data collector callback
2661
- * Called to collect all records for a partition before migration
2868
+ * === OPTIMIZATION 2 & 3: Batched Broadcast with Serialization Caching ===
2869
+ * Groups clients by their permission roles and serializes once per group.
2870
+ * Also batches multiple events into a single SERVER_BATCH_EVENT message.
2871
+ * === OPTIMIZATION 4: Subscription-based Routing ===
2872
+ * Only sends events to clients with active subscriptions for affected maps.
2662
2873
  */
2663
- setDataCollector(collector: (partitionId: number) => Promise<Uint8Array[]>): void;
2874
+ private broadcastBatch;
2664
2875
  /**
2665
- * Set the data storer callback
2666
- * Called to store received records after successful migration
2876
+ * Helper method to get role signature for a client (for caching key)
2667
2877
  */
2668
- setDataStorer(storer: (partitionId: number, data: Uint8Array[]) => Promise<void>): void;
2878
+ private getClientRoleSignature;
2669
2879
  /**
2670
- * Plan migration for topology change
2880
+ * === BACKPRESSURE: Synchronous Broadcast ===
2881
+ * Same as broadcastBatch but waits for all sends to complete.
2882
+ * Used when backpressure forces sync processing to drain the pipeline.
2671
2883
  */
2672
- planMigration(oldDistribution: Map<number, PartitionDistribution>, newDistribution: Map<number, PartitionDistribution>): void;
2884
+ private broadcastBatchSync;
2885
+ private setupClusterListeners;
2886
+ private executeLocalQuery;
2673
2887
  /**
2674
- * Start batch processing timer
2888
+ * Convert server Query format to core Query format for indexed execution.
2889
+ * Returns null if conversion is not possible (complex queries).
2675
2890
  */
2676
- private startBatchProcessing;
2891
+ private convertToCoreQuery;
2677
2892
  /**
2678
- * Stop batch processing
2893
+ * Convert predicate node to core Query format.
2679
2894
  */
2680
- private stopBatchProcessing;
2895
+ private predicateToCoreQuery;
2681
2896
  /**
2682
- * Start next batch of migrations
2897
+ * Convert server operator to core query type.
2683
2898
  */
2684
- startNextBatch(): Promise<void>;
2899
+ private convertOperator;
2900
+ private finalizeClusterQuery;
2685
2901
  /**
2686
- * Start migration for a single partition
2902
+ * Core operation application logic shared between processLocalOp and processLocalOpForBatch.
2903
+ * Handles map merge, storage persistence, query evaluation, and event generation.
2904
+ *
2905
+ * @returns Event payload for broadcasting (or null if operation failed)
2687
2906
  */
2688
- private startPartitionMigration;
2907
+ private applyOpToMap;
2689
2908
  /**
2690
- * Split records into chunks
2909
+ * Apply replicated operation from another node (callback for ReplicationPipeline)
2910
+ * This is called when we receive a replicated operation as a backup node
2691
2911
  */
2692
- private chunkify;
2912
+ private applyReplicatedOperation;
2693
2913
  /**
2694
- * Calculate checksum for a chunk using native xxhash
2914
+ * Build OpContext for interceptors.
2695
2915
  */
2696
- private calculateChecksum;
2916
+ private buildOpContext;
2697
2917
  /**
2698
- * Calculate checksum for all partition records using streaming xxhash
2918
+ * Run onBeforeOp interceptors. Returns modified op or null if dropped.
2699
2919
  */
2700
- private calculatePartitionChecksum;
2920
+ private runBeforeInterceptors;
2701
2921
  /**
2702
- * Wait for chunk acknowledgment
2922
+ * Run onAfterOp interceptors (fire-and-forget).
2703
2923
  */
2704
- private waitForChunkAck;
2924
+ private runAfterInterceptors;
2925
+ private handleLockGranted;
2926
+ private processLocalOp;
2705
2927
  /**
2706
- * Wait for migration verification
2928
+ * === OPTIMIZATION 1: Async Batch Processing with Backpressure ===
2929
+ * Processes validated operations asynchronously after ACK has been sent.
2930
+ * Uses BackpressureRegulator to periodically force sync processing and
2931
+ * prevent unbounded accumulation of async work.
2707
2932
  */
2708
- private waitForVerification;
2933
+ private processBatchAsync;
2709
2934
  /**
2710
- * Handle successful migration completion
2935
+ * === BACKPRESSURE: Synchronous Batch Processing ===
2936
+ * Processes operations synchronously, waiting for broadcast completion.
2937
+ * Used when backpressure forces sync to drain the pipeline.
2711
2938
  */
2712
- private onMigrationComplete;
2939
+ private processBatchSync;
2713
2940
  /**
2714
- * Handle migration failure
2941
+ * Forward operation to owner node and wait for completion.
2942
+ * Used in sync processing mode.
2715
2943
  */
2716
- private onMigrationFailed;
2944
+ private forwardOpAndWait;
2717
2945
  /**
2718
- * Handle MIGRATION_START message
2946
+ * Process a single operation for batch processing.
2947
+ * Uses shared applyOpToMap but collects events instead of broadcasting immediately.
2719
2948
  */
2720
- private handleMigrationStart;
2949
+ private processLocalOpForBatch;
2950
+ private handleClusterEvent;
2951
+ getMap(name: string, typeHint?: 'LWW' | 'OR'): LWWMap<string, any> | ORMap<string, any>;
2721
2952
  /**
2722
- * Handle MIGRATION_CHUNK message
2953
+ * Returns map after ensuring it's fully loaded from storage.
2954
+ * Use this for queries to avoid returning empty results during initial load.
2723
2955
  */
2724
- private handleMigrationChunk;
2956
+ getMapAsync(name: string, typeHint?: 'LWW' | 'OR'): Promise<LWWMap<string, any> | ORMap<string, any>>;
2725
2957
  /**
2726
- * Handle MIGRATION_COMPLETE message
2958
+ * Phase 10.04: Get local record for anti-entropy repair
2959
+ * Returns the LWWRecord for a key, used by RepairScheduler
2727
2960
  */
2728
- private handleMigrationComplete;
2961
+ private getLocalRecord;
2729
2962
  /**
2730
- * Handle MIGRATION_CHUNK_ACK message
2963
+ * Phase 10.04: Apply repaired record from anti-entropy repair
2964
+ * Used by RepairScheduler to apply resolved conflicts
2731
2965
  */
2732
- private handleMigrationChunkAck;
2966
+ private applyRepairRecord;
2967
+ private loadMapFromStorage;
2968
+ private startGarbageCollection;
2733
2969
  /**
2734
- * Handle MIGRATION_VERIFY message
2970
+ * Starts the periodic check for dead clients (those that haven't sent PING).
2735
2971
  */
2736
- private handleMigrationVerify;
2972
+ private startHeartbeatCheck;
2737
2973
  /**
2738
- * Reassemble chunks into continuous data
2974
+ * Handles incoming PING message from client.
2975
+ * Responds with PONG immediately.
2739
2976
  */
2740
- private reassemble;
2977
+ private handlePing;
2741
2978
  /**
2742
- * Deserialize records from chunk data
2979
+ * Checks if a client is still alive based on heartbeat.
2743
2980
  */
2744
- private deserializeRecords;
2981
+ isClientAlive(clientId: string): boolean;
2745
2982
  /**
2746
- * Setup cluster message handlers
2983
+ * Returns how long the client has been idle (no PING received).
2984
+ */
2985
+ getClientIdleTime(clientId: string): number;
2986
+ /**
2987
+ * Evicts clients that haven't sent a PING within the timeout period.
2988
+ */
2989
+ private evictDeadClients;
2990
+ private reportLocalHlc;
2991
+ private handleGcReport;
2992
+ private performGarbageCollection;
2993
+ private buildTLSOptions;
2994
+ /**
2995
+ * Get effective Write Concern level for an operation.
2996
+ * Per-op writeConcern overrides batch-level.
2747
2997
  */
2748
- private setupMessageHandlers;
2998
+ private getEffectiveWriteConcern;
2749
2999
  /**
2750
- * Check if a partition is currently migrating
3000
+ * Convert string WriteConcern value to enum.
2751
3001
  */
2752
- isActive(partitionId: number): boolean;
3002
+ private stringToWriteConcern;
2753
3003
  /**
2754
- * Get migration status
3004
+ * Process batch with Write Concern tracking.
3005
+ * Notifies WriteAckManager at each stage of processing.
2755
3006
  */
2756
- getStatus(): MigrationStatus;
3007
+ private processBatchAsyncWithWriteConcern;
2757
3008
  /**
2758
- * Get migration metrics
3009
+ * Synchronous batch processing with Write Concern.
2759
3010
  */
2760
- getMetrics(): MigrationMetrics;
3011
+ private processBatchSyncWithWriteConcern;
2761
3012
  /**
2762
- * Cancel all active and queued migrations
3013
+ * Process a single operation with Write Concern level notifications.
2763
3014
  */
2764
- cancelAll(): Promise<void>;
3015
+ private processLocalOpWithWriteConcern;
2765
3016
  /**
2766
- * Cleanup resources (sync version for backwards compatibility)
3017
+ * Persist operation synchronously (blocking).
3018
+ * Used for PERSISTED Write Concern.
2767
3019
  */
2768
- close(): void;
3020
+ private persistOpSync;
2769
3021
  /**
2770
- * Async cleanup - waits for cancellation to complete
3022
+ * Persist operation asynchronously (fire-and-forget).
3023
+ * Used for non-PERSISTED Write Concern levels.
2771
3024
  */
2772
- closeAsync(): Promise<void>;
3025
+ private persistOpAsync;
2773
3026
  }
2774
3027
 
2775
- interface PartitionDistribution {
2776
- owner: string;
2777
- backups: string[];
3028
+ interface PostgresAdapterOptions {
3029
+ tableName?: string;
2778
3030
  }
2779
- interface PartitionServiceEvents {
2780
- 'rebalanced': (map: PartitionMap, changes: PartitionChange[]) => void;
2781
- 'partitionMoved': (info: {
2782
- partitionId: number;
2783
- previousOwner: string;
2784
- newOwner: string;
2785
- version: number;
2786
- }) => void;
3031
+ declare class PostgresAdapter implements IServerStorage {
3032
+ private pool;
3033
+ private tableName;
3034
+ constructor(configOrPool: PoolConfig | Pool, options?: PostgresAdapterOptions);
3035
+ initialize(): Promise<void>;
3036
+ close(): Promise<void>;
3037
+ load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
3038
+ loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
3039
+ loadAllKeys(mapName: string): Promise<string[]>;
3040
+ store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
3041
+ storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
3042
+ delete(mapName: string, key: string): Promise<void>;
3043
+ deleteAll(mapName: string, keys: string[]): Promise<void>;
3044
+ private mapRowToRecord;
3045
+ private isORMapValue;
2787
3046
  }
2788
- interface PartitionServiceConfig {
2789
- /** Enable gradual rebalancing (default: false for backward compatibility) */
2790
- gradualRebalancing: boolean;
2791
- /** Migration configuration */
2792
- migration: Partial<MigrationConfig>;
3047
+
3048
+ /**
3049
+ * In-memory implementation of IServerStorage.
3050
+ * Useful for development, testing, and demos without requiring a database.
3051
+ *
3052
+ * Note: Data is lost when the server restarts.
3053
+ */
3054
+ declare class MemoryServerAdapter implements IServerStorage {
3055
+ private storage;
3056
+ initialize(): Promise<void>;
3057
+ close(): Promise<void>;
3058
+ private getMap;
3059
+ load(mapName: string, key: string): Promise<StorageValue<any> | undefined>;
3060
+ loadAll(mapName: string, keys: string[]): Promise<Map<string, StorageValue<any>>>;
3061
+ loadAllKeys(mapName: string): Promise<string[]>;
3062
+ store(mapName: string, key: string, record: StorageValue<any>): Promise<void>;
3063
+ storeAll(mapName: string, records: Map<string, StorageValue<any>>): Promise<void>;
3064
+ delete(mapName: string, key: string): Promise<void>;
3065
+ deleteAll(mapName: string, keys: string[]): Promise<void>;
2793
3066
  }
2794
- declare class PartitionService extends EventEmitter {
2795
- private cluster;
2796
- private partitions;
2797
- private readonly PARTITION_COUNT;
2798
- private readonly BACKUP_COUNT;
2799
- private mapVersion;
2800
- private lastRebalanceTime;
3067
+
3068
+ declare class SecurityManager {
3069
+ private policies;
3070
+ constructor(policies?: PermissionPolicy[]);
3071
+ addPolicy(policy: PermissionPolicy): void;
3072
+ checkPermission(principal: Principal, mapName: string, action: PermissionType): boolean;
3073
+ filterObject(object: any, principal: Principal, mapName: string): any;
3074
+ private hasRole;
3075
+ private matchesMap;
3076
+ }
3077
+
3078
+ declare const logger: pino.Logger<never, boolean>;
3079
+ type Logger = typeof logger;
3080
+
3081
+ /**
3082
+ * ConnectionRateLimiter - Rate limiter for incoming WebSocket connections.
3083
+ *
3084
+ * Implements connection rate limiting to prevent connection storms and
3085
+ * protect the server from being overwhelmed during high load scenarios.
3086
+ *
3087
+ * Features:
3088
+ * - Limits connections per second to prevent TCP backlog exhaustion
3089
+ * - Tracks pending connections (in-progress handshakes)
3090
+ * - Provides graceful rejection when limits are exceeded
3091
+ * - Auto-resets counters after cooldown period
3092
+ */
3093
+ interface RateLimiterConfig {
3094
+ /** Maximum new connections allowed per second (default: 100) */
3095
+ maxConnectionsPerSecond: number;
3096
+ /** Maximum pending connections waiting for handshake (default: 1000) */
3097
+ maxPendingConnections: number;
3098
+ /** Cooldown period in ms after which counters reset (default: 1000) */
3099
+ cooldownMs: number;
3100
+ }
3101
+ interface RateLimiterStats {
3102
+ /** Current connections per second rate */
3103
+ connectionsPerSecond: number;
3104
+ /** Number of connections currently pending (handshake in progress) */
3105
+ pendingConnections: number;
3106
+ /** Total connections established since start */
3107
+ totalConnections: number;
3108
+ /** Total connections rejected due to rate limiting */
3109
+ totalRejected: number;
3110
+ }
3111
+ declare class ConnectionRateLimiter {
2801
3112
  private config;
2802
- private migrationManager;
2803
- constructor(cluster: ClusterManager, config?: Partial<PartitionServiceConfig>);
2804
- /**
2805
- * Handle membership change
2806
- */
2807
- private onMembershipChange;
2808
- getPartitionId(key: string): number;
2809
- getDistribution(key: string): PartitionDistribution;
2810
- getOwner(key: string): string;
2811
- isLocalOwner(key: string): boolean;
2812
- isLocalBackup(key: string): boolean;
2813
- isRelated(key: string): boolean;
2814
- /**
2815
- * Get current partition map version
2816
- */
2817
- getMapVersion(): number;
2818
- /**
2819
- * Generate full PartitionMap for client consumption
2820
- */
2821
- getPartitionMap(): PartitionMap;
3113
+ /** Connection attempts in current window */
3114
+ private connectionCount;
3115
+ /** Timestamp when current window started */
3116
+ private windowStart;
3117
+ /** Currently pending connections (handshake in progress) */
3118
+ private pendingCount;
3119
+ /** Total connections established since start */
3120
+ private totalConnections;
3121
+ /** Total connections rejected since start */
3122
+ private totalRejected;
3123
+ constructor(config?: Partial<RateLimiterConfig>);
2822
3124
  /**
2823
- * Get partition info by ID
3125
+ * Check if a new connection should be accepted.
3126
+ * @returns true if the connection should be accepted, false if it should be rejected
2824
3127
  */
2825
- getPartitionInfo(partitionId: number): PartitionInfo | null;
3128
+ shouldAccept(): boolean;
2826
3129
  /**
2827
- * Get owner node for a partition ID
3130
+ * Register a connection attempt.
3131
+ * Call this when a new connection is initiated (before handshake completes).
2828
3132
  */
2829
- getPartitionOwner(partitionId: number): string | null;
2830
- private rebalance;
3133
+ onConnectionAttempt(): void;
2831
3134
  /**
2832
- * Perform gradual rebalancing using MigrationManager
3135
+ * Register that a connection has been established (handshake complete).
3136
+ * Call this when the connection is fully established and authenticated.
2833
3137
  */
2834
- private rebalanceGradual;
3138
+ onConnectionEstablished(): void;
2835
3139
  /**
2836
- * Set partition owner (called after migration completes)
3140
+ * Register that a connection has been closed.
3141
+ * Call this when a pending connection is closed before completing handshake.
2837
3142
  */
2838
- setOwner(partitionId: number, nodeId: string): void;
3143
+ onConnectionClosed(): void;
2839
3144
  /**
2840
- * Get backups for a partition
3145
+ * Register that a connection was rejected.
3146
+ * Call this when shouldAccept() returns false and the connection is rejected.
2841
3147
  */
2842
- getBackups(partitionId: number): string[];
3148
+ onConnectionRejected(): void;
2843
3149
  /**
2844
- * Get migration status
3150
+ * Decrease pending count when a connection times out or fails.
3151
+ * Call this when a pending connection fails to complete handshake.
2845
3152
  */
2846
- getMigrationStatus(): MigrationStatus | null;
3153
+ onPendingConnectionFailed(): void;
2847
3154
  /**
2848
- * Check if partition is currently migrating
3155
+ * Get current rate limiter statistics.
2849
3156
  */
2850
- isMigrating(partitionId: number): boolean;
3157
+ getStats(): RateLimiterStats;
2851
3158
  /**
2852
- * Check if any partition is currently migrating
3159
+ * Reset the rate limiter state.
3160
+ * Useful for testing or when recovering from errors.
2853
3161
  */
2854
- isRebalancing(): boolean;
3162
+ reset(): void;
2855
3163
  /**
2856
- * Get MigrationManager for configuration
3164
+ * Update configuration at runtime.
2857
3165
  */
2858
- getMigrationManager(): MigrationManager | null;
3166
+ updateConfig(config: Partial<RateLimiterConfig>): void;
2859
3167
  /**
2860
- * Cancel all migrations
3168
+ * Check if window has expired and reset if needed.
2861
3169
  */
2862
- cancelMigrations(): Promise<void>;
3170
+ private maybeResetWindow;
3171
+ }
3172
+
3173
+ declare class TimestampInterceptor implements IInterceptor {
3174
+ name: string;
3175
+ onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp>;
3176
+ }
3177
+
3178
+ interface RateLimitConfig {
3179
+ windowMs: number;
3180
+ maxOps: number;
3181
+ }
3182
+ declare class RateLimitInterceptor implements IInterceptor {
3183
+ name: string;
3184
+ private limits;
3185
+ private config;
3186
+ constructor(config?: RateLimitConfig);
3187
+ onBeforeOp(op: ServerOp, context: OpContext): Promise<ServerOp | null>;
3188
+ onDisconnect(context: any): Promise<void>;
3189
+ }
3190
+
3191
+ /**
3192
+ * Native Module Statistics
3193
+ *
3194
+ * Provides information about available native optimizations.
3195
+ *
3196
+ * Phase 3.05: Integration
3197
+ */
3198
+
3199
+ /**
3200
+ * Native module availability status
3201
+ */
3202
+ interface NativeModuleStatus {
3203
+ /** Native xxHash64 is available and being used */
3204
+ nativeHash: boolean;
3205
+ /** SharedArrayBuffer is available */
3206
+ sharedArrayBuffer: boolean;
3207
+ }
3208
+ /**
3209
+ * Comprehensive native statistics
3210
+ */
3211
+ interface NativeStats {
3212
+ /** Module availability status */
3213
+ modules: NativeModuleStatus;
3214
+ /** Shared memory statistics (if enabled) */
3215
+ sharedMemory: SharedMemoryStats | null;
3216
+ /** Summary of what's being used */
3217
+ summary: string;
2863
3218
  }
3219
+ /**
3220
+ * Check which native modules are available.
3221
+ */
3222
+ declare function getNativeModuleStatus(): NativeModuleStatus;
3223
+ /**
3224
+ * Get native statistics including shared memory.
3225
+ *
3226
+ * @param sharedMemoryManager - Optional SharedMemoryManager instance
3227
+ */
3228
+ declare function getNativeStats(sharedMemoryManager?: SharedMemoryManager): NativeStats;
3229
+ /**
3230
+ * Log native module status to console.
3231
+ */
3232
+ declare function logNativeStatus(): void;
2864
3233
 
2865
3234
  /**
2866
3235
  * LagTracker - Monitors replication lag across cluster nodes
@@ -3687,6 +4056,7 @@ declare class RepairScheduler extends EventEmitter {
3687
4056
  private activeRepairs;
3688
4057
  private scanTimer?;
3689
4058
  private processTimer?;
4059
+ private initialScanTimer?;
3690
4060
  private started;
3691
4061
  private pendingRequests;
3692
4062
  private metrics;
@@ -3955,792 +4325,530 @@ declare class EntryProcessorHandler {
3955
4325
  fallbackScripts: number;
3956
4326
  };
3957
4327
  /**
3958
- * Clear sandbox cache.
3959
- */
3960
- clearCache(processorName?: string): void;
3961
- /**
3962
- * Dispose of the handler and its sandbox.
3963
- */
3964
- dispose(): void;
3965
- }
3966
-
3967
- /**
3968
- * Configuration for ConflictResolverService.
3969
- */
3970
- interface ConflictResolverServiceConfig {
3971
- /** Maximum resolvers per map */
3972
- maxResolversPerMap: number;
3973
- /** Enable sandboxed code execution (requires isolated-vm) */
3974
- enableSandboxedResolvers: boolean;
3975
- /** Default timeout for resolver execution in milliseconds */
3976
- resolverTimeoutMs: number;
3977
- }
3978
- /**
3979
- * Default service configuration.
3980
- */
3981
- declare const DEFAULT_CONFLICT_RESOLVER_CONFIG: ConflictResolverServiceConfig;
3982
- /**
3983
- * Service for managing and executing conflict resolvers.
3984
- *
3985
- * Resolvers are executed in priority order (highest first).
3986
- * The first resolver that returns a non-'local' action wins.
3987
- * If all resolvers return 'local', LWW is used as fallback.
3988
- *
3989
- * ## Design Decisions
3990
- *
3991
- * ### In-Memory Storage
3992
- * Resolvers are stored in memory only (not persisted to database).
3993
- * This is intentional - resolvers represent application logic that should
3994
- * be registered by clients on connection. Benefits:
3995
- * - Simpler architecture without resolver schema migrations
3996
- * - Clients control their own conflict resolution logic
3997
- * - Natural cleanup when client disconnects
3998
- *
3999
- * ### Permission Model
4000
- * Resolver registration requires PUT permission on the target map.
4001
- * This aligns with the principle that if you can write to a map,
4002
- * you can define how your writes are resolved. For stricter control,
4003
- * implement custom permission checks in ServerCoordinator.
4004
- *
4005
- * ### Deletion Handling
4006
- * Deletions (tombstones with null value) are passed through resolvers
4007
- * with `remoteValue: null`. This allows resolvers like IMMUTABLE or
4008
- * OWNER_ONLY to protect against unauthorized deletions.
4009
- */
4010
- declare class ConflictResolverService {
4011
- private resolvers;
4012
- private sandbox;
4013
- private config;
4014
- private onRejectionCallback?;
4015
- private disposed;
4016
- constructor(sandbox: ProcessorSandbox, config?: Partial<ConflictResolverServiceConfig>);
4017
- /**
4018
- * Set callback for merge rejections.
4019
- */
4020
- onRejection(callback: (rejection: MergeRejection) => void): void;
4021
- /**
4022
- * Register a resolver for a map.
4023
- *
4024
- * @param mapName The map this resolver applies to
4025
- * @param resolver The resolver definition
4026
- * @param registeredBy Optional client ID that registered this resolver
4027
- */
4028
- register<V>(mapName: string, resolver: ConflictResolverDef<V>, registeredBy?: string): void;
4029
- /**
4030
- * Unregister a resolver.
4031
- *
4032
- * @param mapName The map name
4033
- * @param resolverName The resolver name to unregister
4034
- * @param clientId Optional - only unregister if registered by this client
4035
- */
4036
- unregister(mapName: string, resolverName: string, clientId?: string): boolean;
4037
- /**
4038
- * Resolve a merge conflict using registered resolvers.
4039
- *
4040
- * @param context The merge context
4041
- * @returns The merge result
4042
- */
4043
- resolve<V>(context: MergeContext<V>): Promise<MergeResult<V>>;
4044
- /**
4045
- * List registered resolvers.
4046
- *
4047
- * @param mapName Optional - filter by map name
4048
- */
4049
- list(mapName?: string): Array<{
4050
- mapName: string;
4051
- name: string;
4052
- priority?: number;
4053
- keyPattern?: string;
4054
- registeredBy?: string;
4055
- }>;
4056
- /**
4057
- * Check if a map has any registered resolvers.
4058
- */
4059
- hasResolvers(mapName: string): boolean;
4060
- /**
4061
- * Get the number of registered resolvers.
4062
- */
4063
- get size(): number;
4064
- /**
4065
- * Clear all registered resolvers.
4066
- *
4067
- * @param mapName Optional - only clear resolvers for specific map
4068
- */
4069
- clear(mapName?: string): void;
4070
- /**
4071
- * Clear resolvers registered by a specific client.
4072
- */
4073
- clearByClient(clientId: string): number;
4074
- /**
4075
- * Dispose the service.
4076
- */
4077
- dispose(): void;
4078
- /**
4079
- * Match a key against a glob-like pattern.
4080
- * Supports * (any chars) and ? (single char).
4081
- */
4082
- private matchKeyPattern;
4083
- /**
4084
- * Compile sandboxed resolver code.
4085
- */
4086
- private compileSandboxed;
4087
- }
4088
-
4089
- /**
4090
- * Configuration for MapWithResolver.
4091
- */
4092
- interface MapWithResolverConfig {
4093
- /** Map name */
4094
- name: string;
4095
- /** Node ID for HLC */
4096
- nodeId: string;
4097
- /** Conflict resolver service */
4098
- resolverService: ConflictResolverService;
4099
- /** Callback for merge rejections */
4100
- onRejection?: (rejection: MergeRejection) => void;
4101
- }
4102
- /**
4103
- * Result of setWithResolver operation.
4104
- */
4105
- interface SetWithResolverResult<V> {
4106
- /** Whether the value was applied */
4107
- applied: boolean;
4108
- /** The merge result */
4109
- result: MergeResult<V>;
4110
- /** The final record if applied */
4111
- record?: LWWRecord<V>;
4112
- }
4113
- /**
4114
- * Extended LWWMap that supports custom conflict resolvers.
4115
- *
4116
- * This wrapper delegates merge operations to ConflictResolverService,
4117
- * allowing custom business logic to intercept and modify merge behavior.
4118
- */
4119
- declare class MapWithResolver<K extends string, V> {
4120
- private map;
4121
- private resolverService;
4122
- private mapName;
4123
- private hlc;
4124
- private onRejection?;
4125
- constructor(config: MapWithResolverConfig);
4126
- /**
4127
- * Get the map name.
4128
- */
4129
- get name(): string;
4130
- /**
4131
- * Get the underlying LWWMap.
4132
- */
4133
- get rawMap(): LWWMap<K, V>;
4134
- /**
4135
- * Get a value by key.
4136
- */
4137
- get(key: K): V | undefined;
4138
- /**
4139
- * Get the full record for a key.
4140
- */
4141
- getRecord(key: K): LWWRecord<V> | undefined;
4142
- /**
4143
- * Get the timestamp for a key.
4144
- */
4145
- getTimestamp(key: K): Timestamp | undefined;
4146
- /**
4147
- * Set a value locally (no resolver).
4148
- * Use for server-initiated writes.
4149
- */
4150
- set(key: K, value: V, ttlMs?: number): LWWRecord<V>;
4151
- /**
4152
- * Set a value with conflict resolution.
4153
- * Use for client-initiated writes.
4154
- *
4155
- * @param key The key to set
4156
- * @param value The new value
4157
- * @param timestamp The client's timestamp
4158
- * @param remoteNodeId The client's node ID
4159
- * @param auth Optional authentication context
4160
- * @returns Result containing applied status and merge result
4161
- */
4162
- setWithResolver(key: K, value: V, timestamp: Timestamp, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
4163
- /**
4164
- * Remove a key.
4165
- */
4166
- remove(key: K): LWWRecord<V>;
4167
- /**
4168
- * Standard merge without resolver (for sync operations).
4169
- */
4170
- merge(key: K, record: LWWRecord<V>): boolean;
4171
- /**
4172
- * Merge with resolver support.
4173
- * Equivalent to setWithResolver but takes a full record.
4174
- */
4175
- mergeWithResolver(key: K, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
4176
- /**
4177
- * Clear all data.
4178
- */
4179
- clear(): void;
4180
- /**
4181
- * Get map size.
4182
- */
4183
- get size(): number;
4184
- /**
4185
- * Iterate over entries.
4186
- */
4187
- entries(): IterableIterator<[K, V]>;
4188
- /**
4189
- * Get all keys.
4190
- */
4191
- allKeys(): IterableIterator<K>;
4192
- /**
4193
- * Subscribe to changes.
4194
- */
4195
- onChange(callback: () => void): () => void;
4196
- /**
4197
- * Get MerkleTree for sync.
4328
+ * Clear sandbox cache.
4198
4329
  */
4199
- getMerkleTree(): _topgunbuild_core.MerkleTree;
4330
+ clearCache(processorName?: string): void;
4200
4331
  /**
4201
- * Prune old tombstones.
4332
+ * Dispose of the handler and its sandbox.
4202
4333
  */
4203
- prune(olderThan: Timestamp): K[];
4334
+ dispose(): void;
4204
4335
  }
4205
4336
 
4206
4337
  /**
4207
- * Configuration for ConflictResolverHandler.
4338
+ * Configuration for ConflictResolverService.
4208
4339
  */
4209
- interface ConflictResolverHandlerConfig {
4210
- /** Node ID for identifying server-side resolvers */
4211
- nodeId: string;
4212
- /** Optional sandbox configuration override */
4213
- sandboxConfig?: Partial<ProcessorSandboxConfig>;
4214
- /** Optional resolver service configuration */
4215
- resolverConfig?: Partial<ConflictResolverServiceConfig>;
4340
+ interface ConflictResolverServiceConfig {
4341
+ /** Maximum resolvers per map */
4342
+ maxResolversPerMap: number;
4343
+ /** Enable sandboxed code execution (requires isolated-vm) */
4344
+ enableSandboxedResolvers: boolean;
4345
+ /** Default timeout for resolver execution in milliseconds */
4346
+ resolverTimeoutMs: number;
4216
4347
  }
4217
4348
  /**
4218
- * Result of merge operation with resolver.
4349
+ * Default service configuration.
4219
4350
  */
4220
- interface MergeWithResolverResult<V> {
4221
- /** Whether the merge was applied */
4222
- applied: boolean;
4223
- /** The merge result details */
4224
- result: MergeResult<V>;
4225
- /** The final record if applied */
4226
- record?: LWWRecord<V>;
4227
- /** Rejection details if rejected */
4228
- rejection?: MergeRejection;
4229
- }
4351
+ declare const DEFAULT_CONFLICT_RESOLVER_CONFIG: ConflictResolverServiceConfig;
4230
4352
  /**
4231
- * Server-side handler for Conflict Resolver operations.
4353
+ * Service for managing and executing conflict resolvers.
4232
4354
  *
4233
- * Responsibilities:
4234
- * - Manage conflict resolver registrations
4235
- * - Execute resolvers during merge operations
4236
- * - Provide merge rejection notifications
4355
+ * Resolvers are executed in priority order (highest first).
4356
+ * The first resolver that returns a non-'local' action wins.
4357
+ * If all resolvers return 'local', LWW is used as fallback.
4358
+ *
4359
+ * ## Design Decisions
4360
+ *
4361
+ * ### In-Memory Storage
4362
+ * Resolvers are stored in memory only (not persisted to database).
4363
+ * This is intentional - resolvers represent application logic that should
4364
+ * be registered by clients on connection. Benefits:
4365
+ * - Simpler architecture without resolver schema migrations
4366
+ * - Clients control their own conflict resolution logic
4367
+ * - Natural cleanup when client disconnects
4368
+ *
4369
+ * ### Permission Model
4370
+ * Resolver registration requires PUT permission on the target map.
4371
+ * This aligns with the principle that if you can write to a map,
4372
+ * you can define how your writes are resolved. For stricter control,
4373
+ * implement custom permission checks in ServerCoordinator.
4374
+ *
4375
+ * ### Deletion Handling
4376
+ * Deletions (tombstones with null value) are passed through resolvers
4377
+ * with `remoteValue: null`. This allows resolvers like IMMUTABLE or
4378
+ * OWNER_ONLY to protect against unauthorized deletions.
4237
4379
  */
4238
- declare class ConflictResolverHandler {
4380
+ declare class ConflictResolverService {
4381
+ private resolvers;
4239
4382
  private sandbox;
4240
- private resolverService;
4241
- /** Reserved for future use (server-side resolver identification) */
4242
- private readonly nodeId;
4243
- private rejectionListeners;
4244
- constructor(config: ConflictResolverHandlerConfig);
4383
+ private config;
4384
+ private onRejectionCallback?;
4385
+ private disposed;
4386
+ constructor(sandbox: ProcessorSandbox, config?: Partial<ConflictResolverServiceConfig>);
4245
4387
  /**
4246
- * Register a conflict resolver for a map.
4388
+ * Set callback for merge rejections.
4389
+ */
4390
+ onRejection(callback: (rejection: MergeRejection) => void): void;
4391
+ /**
4392
+ * Register a resolver for a map.
4247
4393
  *
4248
- * @param mapName The map name
4394
+ * @param mapName The map this resolver applies to
4249
4395
  * @param resolver The resolver definition
4250
- * @param clientId Optional client ID that registered this resolver
4396
+ * @param registeredBy Optional client ID that registered this resolver
4251
4397
  */
4252
- registerResolver<V>(mapName: string, resolver: ConflictResolverDef<V>, clientId?: string): void;
4398
+ register<V>(mapName: string, resolver: ConflictResolverDef<V>, registeredBy?: string): void;
4253
4399
  /**
4254
- * Unregister a conflict resolver.
4400
+ * Unregister a resolver.
4255
4401
  *
4256
4402
  * @param mapName The map name
4257
- * @param resolverName The resolver name
4403
+ * @param resolverName The resolver name to unregister
4258
4404
  * @param clientId Optional - only unregister if registered by this client
4259
4405
  */
4260
- unregisterResolver(mapName: string, resolverName: string, clientId?: string): boolean;
4406
+ unregister(mapName: string, resolverName: string, clientId?: string): boolean;
4407
+ /**
4408
+ * Resolve a merge conflict using registered resolvers.
4409
+ *
4410
+ * @param context The merge context
4411
+ * @returns The merge result
4412
+ */
4413
+ resolve<V>(context: MergeContext<V>): Promise<MergeResult<V>>;
4261
4414
  /**
4262
4415
  * List registered resolvers.
4263
4416
  *
4264
4417
  * @param mapName Optional - filter by map name
4265
4418
  */
4266
- listResolvers(mapName?: string): Array<{
4419
+ list(mapName?: string): Array<{
4267
4420
  mapName: string;
4268
4421
  name: string;
4269
4422
  priority?: number;
4270
4423
  keyPattern?: string;
4424
+ registeredBy?: string;
4271
4425
  }>;
4272
4426
  /**
4273
- * Apply a merge with conflict resolution.
4274
- *
4275
- * Deletions (tombstones) are also passed through resolvers to allow
4276
- * protection via IMMUTABLE, OWNER_ONLY, or similar resolvers.
4277
- * If no custom resolvers are registered, deletions use standard LWW.
4278
- *
4279
- * @param map The LWWMap to merge into
4280
- * @param mapName The map name (for resolver lookup)
4281
- * @param key The key being merged
4282
- * @param record The incoming record
4283
- * @param remoteNodeId The source node ID
4284
- * @param auth Optional authentication context
4427
+ * Check if a map has any registered resolvers.
4285
4428
  */
4286
- mergeWithResolver<V>(map: LWWMap<string, V>, mapName: string, key: string, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<MergeWithResolverResult<V>>;
4429
+ hasResolvers(mapName: string): boolean;
4287
4430
  /**
4288
- * Check if a map has custom resolvers registered.
4431
+ * Get the number of registered resolvers.
4289
4432
  */
4290
- hasResolvers(mapName: string): boolean;
4433
+ get size(): number;
4291
4434
  /**
4292
- * Add a listener for merge rejections.
4435
+ * Clear all registered resolvers.
4436
+ *
4437
+ * @param mapName Optional - only clear resolvers for specific map
4293
4438
  */
4294
- onRejection(listener: (rejection: MergeRejection) => void): () => void;
4439
+ clear(mapName?: string): void;
4295
4440
  /**
4296
4441
  * Clear resolvers registered by a specific client.
4297
4442
  */
4298
4443
  clearByClient(clientId: string): number;
4299
4444
  /**
4300
- * Get the number of registered resolvers.
4445
+ * Dispose the service.
4301
4446
  */
4302
- get resolverCount(): number;
4447
+ dispose(): void;
4303
4448
  /**
4304
- * Check if sandbox is in secure mode.
4449
+ * Match a key against a glob-like pattern.
4450
+ * Supports * (any chars) and ? (single char).
4305
4451
  */
4306
- isSecureMode(): boolean;
4452
+ private matchKeyPattern;
4307
4453
  /**
4308
- * Dispose of the handler.
4454
+ * Compile sandboxed resolver code.
4309
4455
  */
4310
- dispose(): void;
4456
+ private compileSandboxed;
4311
4457
  }
4312
4458
 
4313
4459
  /**
4314
- * IndexConfig Types
4315
- *
4316
- * Configuration types for server-side index management.
4317
- * Used to define indexes per map at server startup.
4318
- *
4319
- * @module config/IndexConfig
4320
- */
4321
- /**
4322
- * Definition of a single index on a map.
4323
- */
4324
- interface IndexDefinition {
4325
- /** Attribute name (supports dot notation for nested attributes, e.g., "user.email") */
4326
- attribute: string;
4327
- /** Index type */
4328
- type: 'hash' | 'navigable';
4329
- /**
4330
- * Comparator type for navigable indexes.
4331
- * Defaults to natural ordering (string/number).
4332
- */
4333
- comparator?: 'number' | 'string' | 'date';
4334
- }
4335
- /**
4336
- * Index configuration for a specific map.
4460
+ * Configuration for MapWithResolver.
4337
4461
  */
4338
- interface MapIndexConfig {
4462
+ interface MapWithResolverConfig {
4339
4463
  /** Map name */
4340
- mapName: string;
4341
- /** Indexes to create on this map */
4342
- indexes: IndexDefinition[];
4464
+ name: string;
4465
+ /** Node ID for HLC */
4466
+ nodeId: string;
4467
+ /** Conflict resolver service */
4468
+ resolverService: ConflictResolverService;
4469
+ /** Callback for merge rejections */
4470
+ onRejection?: (rejection: MergeRejection) => void;
4343
4471
  }
4344
4472
  /**
4345
- * Server-wide index configuration.
4473
+ * Result of setWithResolver operation.
4346
4474
  */
4347
- interface ServerIndexConfig {
4348
- /**
4349
- * Auto-create indexes based on query patterns.
4350
- * When enabled, the server will analyze query patterns and suggest/create indexes.
4351
- * Default: false
4352
- */
4353
- autoIndex?: boolean;
4354
- /**
4355
- * Maximum number of auto-created indexes per map.
4356
- * Prevents unbounded memory growth from auto-indexing.
4357
- * Default: 10
4358
- */
4359
- maxAutoIndexesPerMap?: number;
4360
- /**
4361
- * Pre-configured indexes per map.
4362
- * These indexes are created at map initialization.
4363
- */
4364
- maps?: MapIndexConfig[];
4365
- /**
4366
- * Whether to log index usage statistics.
4367
- * Default: false
4368
- */
4369
- logStats?: boolean;
4370
- /**
4371
- * Interval in milliseconds for logging index statistics.
4372
- * Only used if logStats is true.
4373
- * Default: 60000 (1 minute)
4374
- */
4375
- statsLogInterval?: number;
4475
+ interface SetWithResolverResult<V> {
4476
+ /** Whether the value was applied */
4477
+ applied: boolean;
4478
+ /** The merge result */
4479
+ result: MergeResult<V>;
4480
+ /** The final record if applied */
4481
+ record?: LWWRecord<V>;
4376
4482
  }
4377
4483
  /**
4378
- * Default index configuration.
4379
- */
4380
- declare const DEFAULT_INDEX_CONFIG: ServerIndexConfig;
4381
- /**
4382
- * Validate a ServerIndexConfig object.
4383
- *
4384
- * @param config - Config to validate
4385
- * @returns Array of validation errors (empty if valid)
4386
- */
4387
- declare function validateIndexConfig(config: ServerIndexConfig): string[];
4388
- /**
4389
- * Merge user config with defaults.
4390
- *
4391
- * @param userConfig - User-provided config
4392
- * @returns Merged config with defaults
4393
- */
4394
- declare function mergeWithDefaults(userConfig: Partial<ServerIndexConfig>): ServerIndexConfig;
4395
-
4396
- /**
4397
- * MapFactory Implementation
4398
- *
4399
- * Factory for creating LWWMap or IndexedLWWMap based on configuration.
4400
- * Used by ServerCoordinator to create maps with proper indexes.
4484
+ * Extended LWWMap that supports custom conflict resolvers.
4401
4485
  *
4402
- * @module config/MapFactory
4403
- */
4404
-
4405
- /**
4406
- * Factory for creating indexed or regular CRDT maps.
4486
+ * This wrapper delegates merge operations to ConflictResolverService,
4487
+ * allowing custom business logic to intercept and modify merge behavior.
4407
4488
  */
4408
- declare class MapFactory {
4409
- private readonly config;
4410
- private readonly mapConfigs;
4489
+ declare class MapWithResolver<K extends string, V> {
4490
+ private map;
4491
+ private resolverService;
4492
+ private mapName;
4493
+ private hlc;
4494
+ private onRejection?;
4495
+ constructor(config: MapWithResolverConfig);
4411
4496
  /**
4412
- * Create a MapFactory.
4413
- *
4414
- * @param config - Server index configuration
4497
+ * Get the map name.
4415
4498
  */
4416
- constructor(config?: Partial<ServerIndexConfig>);
4499
+ get name(): string;
4417
4500
  /**
4418
- * Create an LWWMap or IndexedLWWMap based on configuration.
4419
- *
4420
- * @param mapName - Name of the map
4421
- * @param hlc - Hybrid Logical Clock instance
4422
- * @returns LWWMap or IndexedLWWMap depending on configuration
4501
+ * Get the underlying LWWMap.
4423
4502
  */
4424
- createLWWMap<V>(mapName: string, hlc: HLC): LWWMap<string, V> | IndexedLWWMap<string, V>;
4503
+ get rawMap(): LWWMap<K, V>;
4425
4504
  /**
4426
- * Create an ORMap or IndexedORMap based on configuration.
4427
- *
4428
- * @param mapName - Name of the map
4429
- * @param hlc - Hybrid Logical Clock instance
4430
- * @returns ORMap or IndexedORMap depending on configuration
4505
+ * Get a value by key.
4431
4506
  */
4432
- createORMap<V>(mapName: string, hlc: HLC): ORMap<string, V> | IndexedORMap<string, V>;
4507
+ get(key: K): V | undefined;
4433
4508
  /**
4434
- * Add an index to an IndexedLWWMap based on definition.
4509
+ * Get the full record for a key.
4435
4510
  */
4436
- private addIndexToLWWMap;
4511
+ getRecord(key: K): LWWRecord<V> | undefined;
4437
4512
  /**
4438
- * Add an index to an IndexedORMap based on definition.
4513
+ * Get the timestamp for a key.
4439
4514
  */
4440
- private addIndexToORMap;
4515
+ getTimestamp(key: K): Timestamp | undefined;
4441
4516
  /**
4442
- * Create an Attribute for extracting values from records.
4443
- * Supports dot notation for nested paths.
4517
+ * Set a value locally (no resolver).
4518
+ * Use for server-initiated writes.
4444
4519
  */
4445
- private createAttribute;
4520
+ set(key: K, value: V, ttlMs?: number): LWWRecord<V>;
4446
4521
  /**
4447
- * Get a nested value from an object using dot notation.
4522
+ * Set a value with conflict resolution.
4523
+ * Use for client-initiated writes.
4448
4524
  *
4449
- * @param obj - Object to extract value from
4450
- * @param path - Dot-notation path (e.g., "user.email")
4451
- * @returns Value at the path or undefined
4525
+ * @param key The key to set
4526
+ * @param value The new value
4527
+ * @param timestamp The client's timestamp
4528
+ * @param remoteNodeId The client's node ID
4529
+ * @param auth Optional authentication context
4530
+ * @returns Result containing applied status and merge result
4452
4531
  */
4453
- private getNestedValue;
4532
+ setWithResolver(key: K, value: V, timestamp: Timestamp, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
4454
4533
  /**
4455
- * Create a comparator function for navigable indexes.
4534
+ * Remove a key.
4456
4535
  */
4457
- private createComparator;
4536
+ remove(key: K): LWWRecord<V>;
4458
4537
  /**
4459
- * Check if a map should be indexed based on configuration.
4460
- *
4461
- * @param mapName - Name of the map
4462
- * @returns true if map has index configuration
4538
+ * Standard merge without resolver (for sync operations).
4463
4539
  */
4464
- hasIndexConfig(mapName: string): boolean;
4540
+ merge(key: K, record: LWWRecord<V>): boolean;
4465
4541
  /**
4466
- * Get index configuration for a map.
4467
- *
4468
- * @param mapName - Name of the map
4469
- * @returns Map index config or undefined
4542
+ * Merge with resolver support.
4543
+ * Equivalent to setWithResolver but takes a full record.
4470
4544
  */
4471
- getMapConfig(mapName: string): MapIndexConfig | undefined;
4545
+ mergeWithResolver(key: K, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<SetWithResolverResult<V>>;
4472
4546
  /**
4473
- * Get all configured map names.
4474
- *
4475
- * @returns Array of map names with index configuration
4547
+ * Clear all data.
4476
4548
  */
4477
- getConfiguredMaps(): string[];
4549
+ clear(): void;
4478
4550
  /**
4479
- * Get the full server index configuration.
4551
+ * Get map size.
4480
4552
  */
4481
- getConfig(): ServerIndexConfig;
4553
+ get size(): number;
4554
+ /**
4555
+ * Iterate over entries.
4556
+ */
4557
+ entries(): IterableIterator<[K, V]>;
4558
+ /**
4559
+ * Get all keys.
4560
+ */
4561
+ allKeys(): IterableIterator<K>;
4562
+ /**
4563
+ * Subscribe to changes.
4564
+ */
4565
+ onChange(callback: () => void): () => void;
4566
+ /**
4567
+ * Get MerkleTree for sync.
4568
+ */
4569
+ getMerkleTree(): _topgunbuild_core.MerkleTree;
4570
+ /**
4571
+ * Prune old tombstones.
4572
+ */
4573
+ prune(olderThan: Timestamp): K[];
4482
4574
  }
4483
4575
 
4484
4576
  /**
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.
4577
+ * Configuration for ConflictResolverHandler.
4505
4578
  */
4506
- interface SearchConfig extends FullTextIndexConfig {
4579
+ interface ConflictResolverHandlerConfig {
4580
+ /** Node ID for identifying server-side resolvers */
4581
+ nodeId: string;
4582
+ /** Optional sandbox configuration override */
4583
+ sandboxConfig?: Partial<ProcessorSandboxConfig>;
4584
+ /** Optional resolver service configuration */
4585
+ resolverConfig?: Partial<ConflictResolverServiceConfig>;
4507
4586
  }
4508
4587
  /**
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.
4588
+ * Result of merge operation with resolver.
4514
4589
  */
4515
- interface BatchedUpdate {
4516
- key: string;
4517
- value: unknown;
4518
- score: number;
4519
- matchedTerms: string[];
4520
- type: SearchUpdateType;
4590
+ interface MergeWithResolverResult<V> {
4591
+ /** Whether the merge was applied */
4592
+ applied: boolean;
4593
+ /** The merge result details */
4594
+ result: MergeResult<V>;
4595
+ /** The final record if applied */
4596
+ record?: LWWRecord<V>;
4597
+ /** Rejection details if rejected */
4598
+ rejection?: MergeRejection;
4521
4599
  }
4522
4600
  /**
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.
4601
+ * Server-side handler for Conflict Resolver operations.
4528
4602
  *
4529
4603
  * 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
- * ```
4604
+ * - Manage conflict resolver registrations
4605
+ * - Execute resolvers during merge operations
4606
+ * - Provide merge rejection notifications
4551
4607
  */
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();
4608
+ declare class ConflictResolverHandler {
4609
+ private sandbox;
4610
+ private resolverService;
4611
+ /** Reserved for future use (server-side resolver identification) */
4612
+ private readonly nodeId;
4613
+ private rejectionListeners;
4614
+ constructor(config: ConflictResolverHandlerConfig);
4576
4615
  /**
4577
- * Set the callback for sending updates to clients.
4578
- * Called by ServerCoordinator during initialization.
4616
+ * Register a conflict resolver for a map.
4617
+ *
4618
+ * @param mapName The map name
4619
+ * @param resolver The resolver definition
4620
+ * @param clientId Optional client ID that registered this resolver
4621
+ */
4622
+ registerResolver<V>(mapName: string, resolver: ConflictResolverDef<V>, clientId?: string): void;
4623
+ /**
4624
+ * Unregister a conflict resolver.
4625
+ *
4626
+ * @param mapName The map name
4627
+ * @param resolverName The resolver name
4628
+ * @param clientId Optional - only unregister if registered by this client
4629
+ */
4630
+ unregisterResolver(mapName: string, resolverName: string, clientId?: string): boolean;
4631
+ /**
4632
+ * List registered resolvers.
4633
+ *
4634
+ * @param mapName Optional - filter by map name
4635
+ */
4636
+ listResolvers(mapName?: string): Array<{
4637
+ mapName: string;
4638
+ name: string;
4639
+ priority?: number;
4640
+ keyPattern?: string;
4641
+ }>;
4642
+ /**
4643
+ * Apply a merge with conflict resolution.
4644
+ *
4645
+ * Deletions (tombstones) are also passed through resolvers to allow
4646
+ * protection via IMMUTABLE, OWNER_ONLY, or similar resolvers.
4647
+ * If no custom resolvers are registered, deletions use standard LWW.
4648
+ *
4649
+ * @param map The LWWMap to merge into
4650
+ * @param mapName The map name (for resolver lookup)
4651
+ * @param key The key being merged
4652
+ * @param record The incoming record
4653
+ * @param remoteNodeId The source node ID
4654
+ * @param auth Optional authentication context
4655
+ */
4656
+ mergeWithResolver<V>(map: LWWMap<string, V>, mapName: string, key: string, record: LWWRecord<V>, remoteNodeId: string, auth?: MergeContext['auth']): Promise<MergeWithResolverResult<V>>;
4657
+ /**
4658
+ * Check if a map has custom resolvers registered.
4579
4659
  */
4580
- setSendUpdateCallback(callback: SendUpdateCallback): void;
4660
+ hasResolvers(mapName: string): boolean;
4581
4661
  /**
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
4662
+ * Add a listener for merge rejections.
4587
4663
  */
4588
- setSendBatchUpdateCallback(callback: SendBatchUpdateCallback): void;
4664
+ onRejection(listener: (rejection: MergeRejection) => void): () => void;
4589
4665
  /**
4590
- * Set the callback for retrieving document values.
4591
- * Called by ServerCoordinator during initialization.
4666
+ * Clear resolvers registered by a specific client.
4592
4667
  */
4593
- setDocumentValueGetter(getter: (mapName: string, key: string) => unknown | undefined): void;
4668
+ clearByClient(clientId: string): number;
4594
4669
  /**
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)
4670
+ * Get the number of registered resolvers.
4599
4671
  */
4600
- enableSearch(mapName: string, config: SearchConfig): void;
4672
+ get resolverCount(): number;
4601
4673
  /**
4602
- * Disable full-text search for a map.
4603
- *
4604
- * @param mapName - Name of the map to disable FTS for
4674
+ * Check if sandbox is in secure mode.
4605
4675
  */
4606
- disableSearch(mapName: string): void;
4676
+ isSecureMode(): boolean;
4607
4677
  /**
4608
- * Check if FTS is enabled for a map.
4678
+ * Dispose of the handler.
4609
4679
  */
4610
- isSearchEnabled(mapName: string): boolean;
4680
+ dispose(): void;
4681
+ }
4682
+
4683
+ /**
4684
+ * IndexConfig Types
4685
+ *
4686
+ * Configuration types for server-side index management.
4687
+ * Used to define indexes per map at server startup.
4688
+ *
4689
+ * @module config/IndexConfig
4690
+ */
4691
+ /**
4692
+ * Definition of a single index on a map.
4693
+ */
4694
+ interface IndexDefinition {
4695
+ /** Attribute name (supports dot notation for nested attributes, e.g., "user.email") */
4696
+ attribute: string;
4697
+ /** Index type */
4698
+ type: 'hash' | 'navigable';
4611
4699
  /**
4612
- * Get enabled map names.
4700
+ * Comparator type for navigable indexes.
4701
+ * Defaults to natural ordering (string/number).
4613
4702
  */
4614
- getEnabledMaps(): string[];
4703
+ comparator?: 'number' | 'string' | 'date';
4704
+ }
4705
+ /**
4706
+ * Index configuration for a specific map.
4707
+ */
4708
+ interface MapIndexConfig {
4709
+ /** Map name */
4710
+ mapName: string;
4711
+ /** Indexes to create on this map */
4712
+ indexes: IndexDefinition[];
4713
+ }
4714
+ /**
4715
+ * Server-wide index configuration.
4716
+ */
4717
+ interface ServerIndexConfig {
4615
4718
  /**
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
4719
+ * Auto-create indexes based on query patterns.
4720
+ * When enabled, the server will analyze query patterns and suggest/create indexes.
4721
+ * Default: false
4622
4722
  */
4623
- search(mapName: string, query: string, options?: FTSSearchOptions): SearchRespPayload;
4723
+ autoIndex?: boolean;
4624
4724
  /**
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
4725
+ * Maximum number of auto-created indexes per map.
4726
+ * Prevents unbounded memory growth from auto-indexing.
4727
+ * Default: 10
4631
4728
  */
4632
- onDataChange(mapName: string, key: string, value: Record<string, unknown> | null | undefined, changeType: 'add' | 'update' | 'remove'): void;
4729
+ maxAutoIndexesPerMap?: number;
4633
4730
  /**
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
4731
+ * Pre-configured indexes per map.
4732
+ * These indexes are created at map initialization.
4639
4733
  */
4640
- buildIndexFromEntries(mapName: string, entries: Iterable<[string, Record<string, unknown> | null]>): void;
4734
+ maps?: MapIndexConfig[];
4641
4735
  /**
4642
- * Get index statistics for monitoring.
4736
+ * Whether to log index usage statistics.
4737
+ * Default: false
4643
4738
  */
4644
- getIndexStats(mapName: string): {
4645
- documentCount: number;
4646
- fields: string[];
4647
- } | null;
4739
+ logStats?: boolean;
4648
4740
  /**
4649
- * Clear all indexes (for testing or shutdown).
4741
+ * Interval in milliseconds for logging index statistics.
4742
+ * Only used if logStats is true.
4743
+ * Default: 60000 (1 minute)
4650
4744
  */
4651
- clear(): void;
4745
+ statsLogInterval?: number;
4746
+ }
4747
+ /**
4748
+ * Default index configuration.
4749
+ */
4750
+ declare const DEFAULT_INDEX_CONFIG: ServerIndexConfig;
4751
+ /**
4752
+ * Validate a ServerIndexConfig object.
4753
+ *
4754
+ * @param config - Config to validate
4755
+ * @returns Array of validation errors (empty if valid)
4756
+ */
4757
+ declare function validateIndexConfig(config: ServerIndexConfig): string[];
4758
+ /**
4759
+ * Merge user config with defaults.
4760
+ *
4761
+ * @param userConfig - User-provided config
4762
+ * @returns Merged config with defaults
4763
+ */
4764
+ declare function mergeWithDefaults(userConfig: Partial<ServerIndexConfig>): ServerIndexConfig;
4765
+
4766
+ /**
4767
+ * MapFactory Implementation
4768
+ *
4769
+ * Factory for creating LWWMap or IndexedLWWMap based on configuration.
4770
+ * Used by ServerCoordinator to create maps with proper indexes.
4771
+ *
4772
+ * @module config/MapFactory
4773
+ */
4774
+
4775
+ /**
4776
+ * Factory for creating indexed or regular CRDT maps.
4777
+ */
4778
+ declare class MapFactory {
4779
+ private readonly config;
4780
+ private readonly mapConfigs;
4652
4781
  /**
4653
- * Subscribe to live search results.
4654
- * Returns initial results and tracks the subscription for delta updates.
4782
+ * Create a MapFactory.
4655
4783
  *
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
4784
+ * @param config - Server index configuration
4662
4785
  */
4663
- subscribe(clientId: string, subscriptionId: string, mapName: string, query: string, options?: SearchOptions): ServerSearchResult[];
4786
+ constructor(config?: Partial<ServerIndexConfig>);
4664
4787
  /**
4665
- * Unsubscribe from a live search.
4788
+ * Create an LWWMap or IndexedLWWMap based on configuration.
4666
4789
  *
4667
- * @param subscriptionId - Subscription to remove
4790
+ * @param mapName - Name of the map
4791
+ * @param hlc - Hybrid Logical Clock instance
4792
+ * @returns LWWMap or IndexedLWWMap depending on configuration
4668
4793
  */
4669
- unsubscribe(subscriptionId: string): void;
4794
+ createLWWMap<V>(mapName: string, hlc: HLC): LWWMap<string, V> | IndexedLWWMap<string, V>;
4670
4795
  /**
4671
- * Unsubscribe all subscriptions for a client.
4672
- * Called when a client disconnects.
4796
+ * Create an ORMap or IndexedORMap based on configuration.
4673
4797
  *
4674
- * @param clientId - ID of the disconnected client
4798
+ * @param mapName - Name of the map
4799
+ * @param hlc - Hybrid Logical Clock instance
4800
+ * @returns ORMap or IndexedORMap depending on configuration
4675
4801
  */
4676
- unsubscribeClient(clientId: string): void;
4802
+ createORMap<V>(mapName: string, hlc: HLC): ORMap<string, V> | IndexedORMap<string, V>;
4677
4803
  /**
4678
- * Get the number of active subscriptions.
4804
+ * Add an index to an IndexedLWWMap based on definition.
4679
4805
  */
4680
- getSubscriptionCount(): number;
4806
+ private addIndexToLWWMap;
4681
4807
  /**
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
4808
+ * Add an index to an IndexedORMap based on definition.
4689
4809
  */
4690
- private notifySubscribers;
4810
+ private addIndexToORMap;
4691
4811
  /**
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
4812
+ * Create an Attribute for extracting values from records.
4813
+ * Supports dot notation for nested paths.
4702
4814
  */
4703
- private scoreDocument;
4815
+ private createAttribute;
4704
4816
  /**
4705
- * Queue a notification for batched processing.
4706
- * Notifications are collected and processed together after BATCH_INTERVAL.
4817
+ * Get a nested value from an object using dot notation.
4707
4818
  *
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
4819
+ * @param obj - Object to extract value from
4820
+ * @param path - Dot-notation path (e.g., "user.email")
4821
+ * @returns Value at the path or undefined
4712
4822
  */
4713
- queueNotification(mapName: string, key: string, value: Record<string, unknown> | null, changeType: 'add' | 'update' | 'remove'): void;
4823
+ private getNestedValue;
4714
4824
  /**
4715
- * Schedule a flush of pending notifications.
4716
- * Uses setTimeout to batch notifications within BATCH_INTERVAL window.
4825
+ * Create a comparator function for navigable indexes.
4717
4826
  */
4718
- private scheduleNotificationFlush;
4827
+ private createComparator;
4719
4828
  /**
4720
- * Flush all pending notifications.
4721
- * Processes each map's notifications and sends batched updates.
4829
+ * Check if a map should be indexed based on configuration.
4830
+ *
4831
+ * @param mapName - Name of the map
4832
+ * @returns true if map has index configuration
4722
4833
  */
4723
- flushNotifications(): void;
4834
+ hasIndexConfig(mapName: string): boolean;
4724
4835
  /**
4725
- * Process batched notifications for a single map.
4726
- * Computes updates for each subscription and sends as a batch.
4836
+ * Get index configuration for a map.
4727
4837
  *
4728
4838
  * @param mapName - Name of the map
4729
- * @param notifications - Array of pending notifications
4839
+ * @returns Map index config or undefined
4730
4840
  */
4731
- private processBatchedNotifications;
4841
+ getMapConfig(mapName: string): MapIndexConfig | undefined;
4732
4842
  /**
4733
- * Compute the update for a single document change against a subscription.
4734
- * Returns null if no update is needed.
4843
+ * Get all configured map names.
4735
4844
  *
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
4845
+ * @returns Array of map names with index configuration
4742
4846
  */
4743
- private computeSubscriptionUpdate;
4847
+ getConfiguredMaps(): string[];
4848
+ /**
4849
+ * Get the full server index configuration.
4850
+ */
4851
+ getConfig(): ServerIndexConfig;
4744
4852
  }
4745
4853
 
4746
4854
  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 };