agentdb 3.0.0-alpha.11 → 3.0.0-alpha.13

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.
Files changed (107) hide show
  1. package/dist/src/backends/graph/GraphDatabaseAdapter.d.ts +54 -0
  2. package/dist/src/backends/graph/GraphDatabaseAdapter.d.ts.map +1 -1
  3. package/dist/src/backends/graph/GraphDatabaseAdapter.js +125 -0
  4. package/dist/src/backends/graph/GraphDatabaseAdapter.js.map +1 -1
  5. package/dist/src/cli/agentdb-cli.js +0 -0
  6. package/dist/src/controllers/ReflexionMemory.d.ts +50 -0
  7. package/dist/src/controllers/ReflexionMemory.d.ts.map +1 -1
  8. package/dist/src/controllers/ReflexionMemory.js +258 -0
  9. package/dist/src/controllers/ReflexionMemory.js.map +1 -1
  10. package/dist/src/controllers/index.d.ts +2 -0
  11. package/dist/src/controllers/index.d.ts.map +1 -1
  12. package/dist/src/controllers/index.js +2 -0
  13. package/dist/src/controllers/index.js.map +1 -1
  14. package/dist/src/controllers/prerequisites.d.ts +76 -0
  15. package/dist/src/controllers/prerequisites.d.ts.map +1 -0
  16. package/dist/src/controllers/prerequisites.js +235 -0
  17. package/dist/src/controllers/prerequisites.js.map +1 -0
  18. package/dist/src/db-fallback.d.ts.map +1 -1
  19. package/dist/src/db-fallback.js +55 -45
  20. package/dist/src/db-fallback.js.map +1 -1
  21. package/package.json +1 -1
  22. package/dist/schemas/frontier-schema.sql +0 -378
  23. package/dist/schemas/schema.sql +0 -382
  24. package/dist/src/backends/index.cjs +0 -6
  25. package/dist/src/backends/ruvector/GuardedVectorBackend.d.ts +0 -93
  26. package/dist/src/backends/ruvector/GuardedVectorBackend.d.ts.map +0 -1
  27. package/dist/src/backends/ruvector/GuardedVectorBackend.js +0 -182
  28. package/dist/src/backends/ruvector/GuardedVectorBackend.js.map +0 -1
  29. package/dist/src/consensus/RaftConsensus.d.ts +0 -220
  30. package/dist/src/consensus/RaftConsensus.d.ts.map +0 -1
  31. package/dist/src/consensus/RaftConsensus.js +0 -762
  32. package/dist/src/consensus/RaftConsensus.js.map +0 -1
  33. package/dist/src/controllers/HierarchicalMemory.d.ts +0 -197
  34. package/dist/src/controllers/HierarchicalMemory.d.ts.map +0 -1
  35. package/dist/src/controllers/HierarchicalMemory.js +0 -519
  36. package/dist/src/controllers/HierarchicalMemory.js.map +0 -1
  37. package/dist/src/controllers/MemoryConsolidation.d.ts +0 -142
  38. package/dist/src/controllers/MemoryConsolidation.d.ts.map +0 -1
  39. package/dist/src/controllers/MemoryConsolidation.js +0 -479
  40. package/dist/src/controllers/MemoryConsolidation.js.map +0 -1
  41. package/dist/src/controllers/QUICConnection.d.ts +0 -122
  42. package/dist/src/controllers/QUICConnection.d.ts.map +0 -1
  43. package/dist/src/controllers/QUICConnection.js +0 -329
  44. package/dist/src/controllers/QUICConnection.js.map +0 -1
  45. package/dist/src/controllers/QUICConnectionPool.d.ts +0 -83
  46. package/dist/src/controllers/QUICConnectionPool.d.ts.map +0 -1
  47. package/dist/src/controllers/QUICConnectionPool.js +0 -256
  48. package/dist/src/controllers/QUICConnectionPool.js.map +0 -1
  49. package/dist/src/controllers/QUICStreamManager.d.ts +0 -114
  50. package/dist/src/controllers/QUICStreamManager.d.ts.map +0 -1
  51. package/dist/src/controllers/QUICStreamManager.js +0 -267
  52. package/dist/src/controllers/QUICStreamManager.js.map +0 -1
  53. package/dist/src/controllers/StreamingEmbeddingService.d.ts +0 -82
  54. package/dist/src/controllers/StreamingEmbeddingService.d.ts.map +0 -1
  55. package/dist/src/controllers/StreamingEmbeddingService.js +0 -243
  56. package/dist/src/controllers/StreamingEmbeddingService.js.map +0 -1
  57. package/dist/src/controllers/index.cjs +0 -6
  58. package/dist/src/coordination/MultiDatabaseCoordinator.d.ts +0 -348
  59. package/dist/src/coordination/MultiDatabaseCoordinator.d.ts.map +0 -1
  60. package/dist/src/coordination/MultiDatabaseCoordinator.js +0 -803
  61. package/dist/src/coordination/MultiDatabaseCoordinator.js.map +0 -1
  62. package/dist/src/coordination/index.d.ts +0 -10
  63. package/dist/src/coordination/index.d.ts.map +0 -1
  64. package/dist/src/coordination/index.js +0 -10
  65. package/dist/src/coordination/index.js.map +0 -1
  66. package/dist/src/index.cjs +0 -6
  67. package/dist/src/optimizations/RVFOptimizer.d.ts +0 -226
  68. package/dist/src/optimizations/RVFOptimizer.d.ts.map +0 -1
  69. package/dist/src/optimizations/RVFOptimizer.js +0 -541
  70. package/dist/src/optimizations/RVFOptimizer.js.map +0 -1
  71. package/dist/src/security/AttestationLog.d.ts +0 -70
  72. package/dist/src/security/AttestationLog.d.ts.map +0 -1
  73. package/dist/src/security/AttestationLog.js +0 -174
  74. package/dist/src/security/AttestationLog.js.map +0 -1
  75. package/dist/src/security/MutationGuard.d.ts +0 -83
  76. package/dist/src/security/MutationGuard.d.ts.map +0 -1
  77. package/dist/src/security/MutationGuard.js +0 -364
  78. package/dist/src/security/MutationGuard.js.map +0 -1
  79. package/dist/src/security/index.cjs +0 -6
  80. package/dist/src/security/index.d.ts +0 -15
  81. package/dist/src/security/index.d.ts.map +0 -1
  82. package/dist/src/security/index.js +0 -18
  83. package/dist/src/security/index.js.map +0 -1
  84. package/dist/src/services/GNNService.d.ts +0 -173
  85. package/dist/src/services/GNNService.d.ts.map +0 -1
  86. package/dist/src/services/GNNService.js +0 -639
  87. package/dist/src/services/GNNService.js.map +0 -1
  88. package/dist/src/services/GraphTransformerService.d.ts +0 -80
  89. package/dist/src/services/GraphTransformerService.d.ts.map +0 -1
  90. package/dist/src/services/GraphTransformerService.js +0 -369
  91. package/dist/src/services/GraphTransformerService.js.map +0 -1
  92. package/dist/src/services/SemanticRouter.d.ts +0 -83
  93. package/dist/src/services/SemanticRouter.d.ts.map +0 -1
  94. package/dist/src/services/SemanticRouter.js +0 -160
  95. package/dist/src/services/SemanticRouter.js.map +0 -1
  96. package/dist/src/services/SonaTrajectoryService.d.ts +0 -224
  97. package/dist/src/services/SonaTrajectoryService.d.ts.map +0 -1
  98. package/dist/src/services/SonaTrajectoryService.js +0 -539
  99. package/dist/src/services/SonaTrajectoryService.js.map +0 -1
  100. package/dist/src/utils/LegacyAttentionAdapter.d.ts +0 -93
  101. package/dist/src/utils/LegacyAttentionAdapter.d.ts.map +0 -1
  102. package/dist/src/utils/LegacyAttentionAdapter.js +0 -241
  103. package/dist/src/utils/LegacyAttentionAdapter.js.map +0 -1
  104. package/dist/src/utils/vector-math.d.ts +0 -29
  105. package/dist/src/utils/vector-math.d.ts.map +0 -1
  106. package/dist/src/utils/vector-math.js +0 -66
  107. package/dist/src/utils/vector-math.js.map +0 -1
@@ -1,762 +0,0 @@
1
- /**
2
- * RaftConsensus - Fault-Tolerant Distributed Consensus
3
- *
4
- * Implements the Raft consensus algorithm for multi-agent coordination with:
5
- * - Leader election with automatic failover (<1s)
6
- * - Log replication with strong consistency
7
- * - Byzantine fault tolerance (BFT)
8
- * - Gossip protocols for large-scale coordination
9
- * - CRDT synchronization for eventually consistent state
10
- * - Distributed locks with deadlock detection
11
- * - Automatic sharding and partitioning
12
- *
13
- * References:
14
- * - Raft Paper: https://raft.github.io/raft.pdf
15
- * - Byzantine Fault Tolerance: https://pmg.csail.mit.edu/papers/osdi99.pdf
16
- */
17
- import { EventEmitter } from 'events';
18
- import crypto from 'crypto';
19
- // ============================================================================
20
- // RaftConsensus Implementation
21
- // ============================================================================
22
- export class RaftConsensus extends EventEmitter {
23
- config;
24
- state;
25
- peers = new Map();
26
- electionTimer = null;
27
- heartbeatTimer = null;
28
- votesReceived = new Set();
29
- commandQueue = new Map();
30
- // Byzantine Fault Tolerance
31
- privateKey;
32
- publicKeys = new Map();
33
- // Gossip Protocol
34
- gossipInterval = null;
35
- gossipState = new Map();
36
- // CRDT State
37
- crdtStates = new Map();
38
- // Distributed Locks
39
- locks = new Map();
40
- lockCheckInterval = null;
41
- // Metrics
42
- metrics = {
43
- totalElections: 0,
44
- totalLeaderChanges: 0,
45
- totalCommittedEntries: 0,
46
- lastElectionTime: 0,
47
- avgElectionTimeMs: 0,
48
- uptime: Date.now(),
49
- };
50
- constructor(config) {
51
- super();
52
- this.config = {
53
- nodeId: config.nodeId,
54
- nodes: config.nodes,
55
- electionTimeoutMin: config.electionTimeoutMin || 150,
56
- electionTimeoutMax: config.electionTimeoutMax || 300,
57
- heartbeatInterval: config.heartbeatInterval || 50,
58
- maxEntriesPerRequest: config.maxEntriesPerRequest || 100,
59
- snapshotThreshold: config.snapshotThreshold || 10000,
60
- byzantineTolerance: config.byzantineTolerance || false,
61
- quorumSize: config.quorumSize || Math.floor(config.nodes.length / 2) + 1,
62
- };
63
- // Initialize state
64
- this.state = {
65
- currentTerm: 0,
66
- votedFor: null,
67
- log: [],
68
- commitIndex: 0,
69
- lastApplied: 0,
70
- state: 'follower',
71
- leaderId: null,
72
- };
73
- // Initialize peer states
74
- for (const nodeId of this.config.nodes) {
75
- if (nodeId !== this.config.nodeId) {
76
- this.peers.set(nodeId, {
77
- nodeId,
78
- nextIndex: 1,
79
- matchIndex: 0,
80
- lastHeartbeat: Date.now(),
81
- isHealthy: true,
82
- });
83
- }
84
- }
85
- // Setup Byzantine fault tolerance
86
- if (this.config.byzantineTolerance) {
87
- this.setupBFT();
88
- }
89
- // Start as follower
90
- this.becomeFollower(0);
91
- }
92
- // ============================================================================
93
- // Public API
94
- // ============================================================================
95
- /**
96
- * Start the Raft node
97
- */
98
- start() {
99
- this.resetElectionTimer();
100
- this.startGossipProtocol();
101
- this.startLockMonitoring();
102
- this.emit('started', { nodeId: this.config.nodeId });
103
- }
104
- /**
105
- * Stop the Raft node
106
- */
107
- stop() {
108
- this.clearElectionTimer();
109
- this.clearHeartbeatTimer();
110
- this.stopGossipProtocol();
111
- this.stopLockMonitoring();
112
- this.emit('stopped', { nodeId: this.config.nodeId });
113
- }
114
- /**
115
- * Replicate a command to the cluster
116
- */
117
- async replicate(command, timeout = 5000) {
118
- if (this.state.state !== 'leader') {
119
- throw new Error('Not the leader. Leader is: ' + (this.state.leaderId || 'unknown'));
120
- }
121
- const commandId = crypto.randomUUID();
122
- const entry = {
123
- term: this.state.currentTerm,
124
- index: this.state.log.length + 1,
125
- type: 'command',
126
- command,
127
- timestamp: Date.now(),
128
- };
129
- // Sign entry for BFT
130
- if (this.config.byzantineTolerance) {
131
- entry.signature = this.signData(entry);
132
- }
133
- this.state.log.push(entry);
134
- this.emit('log_appended', entry);
135
- // Wait for replication
136
- return new Promise((resolve, reject) => {
137
- const timer = setTimeout(() => {
138
- this.commandQueue.delete(commandId);
139
- reject(new Error('Replication timeout'));
140
- }, timeout);
141
- this.commandQueue.set(commandId, (result) => {
142
- clearTimeout(timer);
143
- resolve(result);
144
- });
145
- // Trigger immediate replication
146
- this.replicateToFollowers();
147
- });
148
- }
149
- /**
150
- * Handle vote request from candidate
151
- */
152
- handleVoteRequest(request) {
153
- // Verify signature for BFT
154
- if (this.config.byzantineTolerance && !this.verifySignature(request, request.signature)) {
155
- return {
156
- term: this.state.currentTerm,
157
- voteGranted: false,
158
- };
159
- }
160
- // If candidate's term is older, reject
161
- if (request.term < this.state.currentTerm) {
162
- return {
163
- term: this.state.currentTerm,
164
- voteGranted: false,
165
- };
166
- }
167
- // Update term if candidate's term is newer
168
- if (request.term > this.state.currentTerm) {
169
- this.becomeFollower(request.term);
170
- }
171
- // Check if we can vote for this candidate
172
- const canVote = (this.state.votedFor === null || this.state.votedFor === request.candidateId) &&
173
- this.isLogUpToDate(request.lastLogIndex, request.lastLogTerm);
174
- if (canVote) {
175
- this.state.votedFor = request.candidateId;
176
- this.resetElectionTimer();
177
- }
178
- const response = {
179
- term: this.state.currentTerm,
180
- voteGranted: canVote,
181
- };
182
- // Sign response for BFT
183
- if (this.config.byzantineTolerance) {
184
- response.signature = this.signData(response);
185
- }
186
- return response;
187
- }
188
- /**
189
- * Handle append entries request from leader
190
- */
191
- handleAppendEntries(request) {
192
- // Verify signature for BFT
193
- if (this.config.byzantineTolerance && !this.verifySignature(request, request.signature)) {
194
- return {
195
- term: this.state.currentTerm,
196
- success: false,
197
- };
198
- }
199
- // If leader's term is older, reject
200
- if (request.term < this.state.currentTerm) {
201
- return {
202
- term: this.state.currentTerm,
203
- success: false,
204
- };
205
- }
206
- // Valid leader, reset election timer
207
- this.resetElectionTimer();
208
- // Update term and leader if needed
209
- if (request.term > this.state.currentTerm) {
210
- this.becomeFollower(request.term);
211
- }
212
- this.state.leaderId = request.leaderId;
213
- // Check log consistency
214
- if (request.prevLogIndex > 0) {
215
- const prevEntry = this.state.log[request.prevLogIndex - 1];
216
- if (!prevEntry || prevEntry.term !== request.prevLogTerm) {
217
- return {
218
- term: this.state.currentTerm,
219
- success: false,
220
- };
221
- }
222
- }
223
- // Append new entries
224
- if (request.entries.length > 0) {
225
- // Remove conflicting entries
226
- this.state.log = this.state.log.slice(0, request.prevLogIndex);
227
- // Append new entries
228
- for (const entry of request.entries) {
229
- this.state.log.push(entry);
230
- }
231
- this.emit('log_replicated', { entries: request.entries });
232
- }
233
- // Update commit index
234
- if (request.leaderCommit > this.state.commitIndex) {
235
- this.state.commitIndex = Math.min(request.leaderCommit, this.state.log.length);
236
- this.applyCommittedEntries();
237
- }
238
- const response = {
239
- term: this.state.currentTerm,
240
- success: true,
241
- matchIndex: this.state.log.length,
242
- };
243
- // Sign response for BFT
244
- if (this.config.byzantineTolerance) {
245
- response.signature = this.signData(response);
246
- }
247
- return response;
248
- }
249
- /**
250
- * Handle vote response (exposed for testing/network layer)
251
- */
252
- handleVoteResponse(response, peerId) {
253
- this.processVoteResponse(response, peerId);
254
- }
255
- /**
256
- * Handle append entries response (exposed for testing/network layer)
257
- */
258
- handleAppendEntriesResponse(response, peerId) {
259
- this.processAppendEntriesResponse(response, peerId);
260
- }
261
- /**
262
- * Get current cluster status
263
- */
264
- getStatus() {
265
- return {
266
- nodeId: this.config.nodeId,
267
- state: this.state.state,
268
- term: this.state.currentTerm,
269
- leaderId: this.state.leaderId,
270
- logLength: this.state.log.length,
271
- commitIndex: this.state.commitIndex,
272
- lastApplied: this.state.lastApplied,
273
- peers: Array.from(this.peers.values()).map(p => ({
274
- nodeId: p.nodeId,
275
- isHealthy: p.isHealthy,
276
- matchIndex: p.matchIndex,
277
- })),
278
- metrics: this.metrics,
279
- };
280
- }
281
- // ============================================================================
282
- // CRDT Operations
283
- // ============================================================================
284
- /**
285
- * Update CRDT state with eventual consistency
286
- */
287
- updateCRDT(key, operation, value) {
288
- let state = this.crdtStates.get(key);
289
- if (!state) {
290
- state = {
291
- type: 'counter',
292
- value: 0,
293
- vectorClock: new Map([[this.config.nodeId, 0]]),
294
- };
295
- this.crdtStates.set(key, state);
296
- }
297
- // Update vector clock
298
- const currentClock = state.vectorClock.get(this.config.nodeId) || 0;
299
- state.vectorClock.set(this.config.nodeId, currentClock + 1);
300
- // Apply operation
301
- switch (operation) {
302
- case 'increment':
303
- state.value = (state.value || 0) + value;
304
- break;
305
- case 'add':
306
- if (!Array.isArray(state.value))
307
- state.value = [];
308
- state.value.push(value);
309
- break;
310
- case 'set':
311
- state.value = value;
312
- break;
313
- }
314
- // Gossip update to peers
315
- this.gossipCRDTUpdate(key, state);
316
- this.emit('crdt_updated', { key, state });
317
- }
318
- /**
319
- * Get CRDT value
320
- */
321
- getCRDT(key) {
322
- return this.crdtStates.get(key)?.value;
323
- }
324
- /**
325
- * Merge CRDT state from remote node
326
- */
327
- mergeCRDT(key, remoteState) {
328
- const localState = this.crdtStates.get(key);
329
- if (!localState) {
330
- this.crdtStates.set(key, remoteState);
331
- return;
332
- }
333
- // Merge vector clocks
334
- for (const [nodeId, clock] of remoteState.vectorClock.entries()) {
335
- const localClock = localState.vectorClock.get(nodeId) || 0;
336
- localState.vectorClock.set(nodeId, Math.max(localClock, clock));
337
- }
338
- // Merge values based on type
339
- if (localState.type === 'counter') {
340
- localState.value = Math.max(localState.value, remoteState.value);
341
- }
342
- else if (localState.type === 'set') {
343
- localState.value = [...new Set([...localState.value, ...remoteState.value])];
344
- }
345
- this.emit('crdt_merged', { key, state: localState });
346
- }
347
- // ============================================================================
348
- // Distributed Locks
349
- // ============================================================================
350
- /**
351
- * Acquire distributed lock
352
- */
353
- async acquireLock(key, ttlMs = 30000) {
354
- if (this.state.state !== 'leader') {
355
- throw new Error('Only leader can manage locks');
356
- }
357
- const lock = this.locks.get(key);
358
- const now = Date.now();
359
- // Check if lock is available
360
- if (lock && lock.holder && lock.expiresAt > now) {
361
- // Lock is held, add to waiters
362
- lock.waiters.push(this.config.nodeId);
363
- return false;
364
- }
365
- // Acquire lock
366
- this.locks.set(key, {
367
- key,
368
- holder: this.config.nodeId,
369
- acquiredAt: now,
370
- expiresAt: now + ttlMs,
371
- waiters: [],
372
- });
373
- // Replicate lock acquisition
374
- await this.replicate({
375
- type: 'lock_acquire',
376
- key,
377
- holder: this.config.nodeId,
378
- ttlMs,
379
- });
380
- this.emit('lock_acquired', { key, holder: this.config.nodeId });
381
- return true;
382
- }
383
- /**
384
- * Release distributed lock
385
- */
386
- async releaseLock(key) {
387
- if (this.state.state !== 'leader') {
388
- throw new Error('Only leader can manage locks');
389
- }
390
- const lock = this.locks.get(key);
391
- if (!lock || lock.holder !== this.config.nodeId) {
392
- throw new Error('Lock not held by this node');
393
- }
394
- // Release lock
395
- this.locks.delete(key);
396
- // Replicate lock release
397
- await this.replicate({
398
- type: 'lock_release',
399
- key,
400
- holder: this.config.nodeId,
401
- });
402
- this.emit('lock_released', { key, holder: this.config.nodeId });
403
- // Notify next waiter
404
- if (lock.waiters.length > 0) {
405
- const nextHolder = lock.waiters.shift();
406
- this.emit('lock_available', { key, nextHolder });
407
- }
408
- }
409
- /**
410
- * Check for deadlocks
411
- */
412
- detectDeadlocks() {
413
- const waitGraph = new Map();
414
- const deadlocks = [];
415
- // Build wait-for graph
416
- for (const lock of this.locks.values()) {
417
- if (lock.holder && lock.waiters.length > 0) {
418
- for (const waiter of lock.waiters) {
419
- const edges = waitGraph.get(waiter) || [];
420
- edges.push(lock.holder);
421
- waitGraph.set(waiter, edges);
422
- }
423
- }
424
- }
425
- // Detect cycles using DFS
426
- const visited = new Set();
427
- const recStack = new Set();
428
- const detectCycle = (node, path) => {
429
- visited.add(node);
430
- recStack.add(node);
431
- path.push(node);
432
- const neighbors = waitGraph.get(node) || [];
433
- for (const neighbor of neighbors) {
434
- if (!visited.has(neighbor)) {
435
- if (detectCycle(neighbor, [...path])) {
436
- return true;
437
- }
438
- }
439
- else if (recStack.has(neighbor)) {
440
- // Found cycle
441
- const cycleStart = path.indexOf(neighbor);
442
- deadlocks.push(path.slice(cycleStart));
443
- return true;
444
- }
445
- }
446
- recStack.delete(node);
447
- return false;
448
- };
449
- for (const node of waitGraph.keys()) {
450
- if (!visited.has(node)) {
451
- detectCycle(node, []);
452
- }
453
- }
454
- return deadlocks;
455
- }
456
- // ============================================================================
457
- // Private Methods - Leader Election
458
- // ============================================================================
459
- becomeFollower(term) {
460
- this.state.state = 'follower';
461
- this.state.currentTerm = term;
462
- this.state.votedFor = null;
463
- this.clearHeartbeatTimer();
464
- this.resetElectionTimer();
465
- this.emit('state_changed', { state: 'follower', term });
466
- }
467
- becomeCandidate() {
468
- this.state.state = 'candidate';
469
- this.state.currentTerm++;
470
- this.state.votedFor = this.config.nodeId;
471
- this.votesReceived.clear();
472
- this.votesReceived.add(this.config.nodeId);
473
- this.metrics.totalElections++;
474
- const electionStart = Date.now();
475
- this.emit('state_changed', { state: 'candidate', term: this.state.currentTerm });
476
- // Request votes from peers
477
- this.requestVotes();
478
- // Reset election timer
479
- this.resetElectionTimer();
480
- // Track election time
481
- this.once('state_changed', (event) => {
482
- if (event.state === 'leader') {
483
- const electionTime = Date.now() - electionStart;
484
- this.metrics.lastElectionTime = electionTime;
485
- this.metrics.avgElectionTimeMs =
486
- (this.metrics.avgElectionTimeMs * (this.metrics.totalElections - 1) + electionTime) /
487
- this.metrics.totalElections;
488
- }
489
- });
490
- }
491
- becomeLeader() {
492
- this.state.state = 'leader';
493
- this.state.leaderId = this.config.nodeId;
494
- this.clearElectionTimer();
495
- this.metrics.totalLeaderChanges++;
496
- // Initialize peer state
497
- for (const peer of this.peers.values()) {
498
- peer.nextIndex = this.state.log.length + 1;
499
- peer.matchIndex = 0;
500
- }
501
- // Send initial heartbeat
502
- this.sendHeartbeat();
503
- // Start heartbeat timer
504
- this.heartbeatTimer = setInterval(() => {
505
- this.sendHeartbeat();
506
- }, this.config.heartbeatInterval);
507
- this.emit('state_changed', { state: 'leader', term: this.state.currentTerm });
508
- this.emit('leader_elected', { leaderId: this.config.nodeId });
509
- }
510
- requestVotes() {
511
- const request = {
512
- term: this.state.currentTerm,
513
- candidateId: this.config.nodeId,
514
- lastLogIndex: this.state.log.length,
515
- lastLogTerm: this.state.log[this.state.log.length - 1]?.term || 0,
516
- };
517
- // Sign request for BFT
518
- if (this.config.byzantineTolerance) {
519
- request.signature = this.signData(request);
520
- }
521
- // In real implementation, send to all peers
522
- // For now, emit event for testing
523
- this.emit('vote_request', request);
524
- }
525
- processVoteResponse(response, peerId) {
526
- // Verify signature for BFT
527
- if (this.config.byzantineTolerance && !this.verifySignature(response, response.signature)) {
528
- return;
529
- }
530
- // Ignore if no longer candidate
531
- if (this.state.state !== 'candidate') {
532
- return;
533
- }
534
- // Update term if response has newer term
535
- if (response.term > this.state.currentTerm) {
536
- this.becomeFollower(response.term);
537
- return;
538
- }
539
- // Count vote
540
- if (response.voteGranted) {
541
- this.votesReceived.add(peerId);
542
- // Check if we have quorum
543
- if (this.votesReceived.size >= this.config.quorumSize) {
544
- this.becomeLeader();
545
- }
546
- }
547
- }
548
- isLogUpToDate(lastLogIndex, lastLogTerm) {
549
- const ourLastIndex = this.state.log.length;
550
- const ourLastTerm = this.state.log[ourLastIndex - 1]?.term || 0;
551
- // Candidate's log is more up-to-date if:
552
- // 1. Last term is greater, OR
553
- // 2. Last term is same but index is greater or equal
554
- return (lastLogTerm > ourLastTerm ||
555
- (lastLogTerm === ourLastTerm && lastLogIndex >= ourLastIndex));
556
- }
557
- // ============================================================================
558
- // Private Methods - Log Replication
559
- // ============================================================================
560
- sendHeartbeat() {
561
- this.replicateToFollowers();
562
- }
563
- replicateToFollowers() {
564
- for (const [peerId, peer] of this.peers.entries()) {
565
- const prevLogIndex = peer.nextIndex - 1;
566
- const prevLogTerm = prevLogIndex > 0 ? this.state.log[prevLogIndex - 1]?.term || 0 : 0;
567
- const entries = this.state.log.slice(peer.nextIndex - 1, peer.nextIndex - 1 + this.config.maxEntriesPerRequest);
568
- const request = {
569
- term: this.state.currentTerm,
570
- leaderId: this.config.nodeId,
571
- prevLogIndex,
572
- prevLogTerm,
573
- entries,
574
- leaderCommit: this.state.commitIndex,
575
- };
576
- // Sign request for BFT
577
- if (this.config.byzantineTolerance) {
578
- request.signature = this.signData(request);
579
- }
580
- // In real implementation, send to peer
581
- // For now, emit event for testing
582
- this.emit('append_entries', { peerId, request });
583
- }
584
- }
585
- processAppendEntriesResponse(response, peerId) {
586
- // Verify signature for BFT
587
- if (this.config.byzantineTolerance && !this.verifySignature(response, response.signature)) {
588
- return;
589
- }
590
- // Ignore if no longer leader
591
- if (this.state.state !== 'leader') {
592
- return;
593
- }
594
- const peer = this.peers.get(peerId);
595
- if (!peer)
596
- return;
597
- // Update term if response has newer term
598
- if (response.term > this.state.currentTerm) {
599
- this.becomeFollower(response.term);
600
- return;
601
- }
602
- if (response.success) {
603
- // Update peer state
604
- if (response.matchIndex !== undefined) {
605
- peer.matchIndex = response.matchIndex;
606
- peer.nextIndex = response.matchIndex + 1;
607
- }
608
- // Update commit index
609
- this.updateCommitIndex();
610
- }
611
- else {
612
- // Decrement nextIndex and retry
613
- peer.nextIndex = Math.max(1, peer.nextIndex - 1);
614
- }
615
- }
616
- updateCommitIndex() {
617
- // Find highest index replicated on majority
618
- const matchIndices = Array.from(this.peers.values())
619
- .map(p => p.matchIndex)
620
- .sort((a, b) => b - a);
621
- const majorityIndex = matchIndices[Math.floor(this.config.quorumSize / 2)];
622
- if (majorityIndex > this.state.commitIndex) {
623
- const entry = this.state.log[majorityIndex - 1];
624
- if (entry && entry.term === this.state.currentTerm) {
625
- this.state.commitIndex = majorityIndex;
626
- this.metrics.totalCommittedEntries++;
627
- this.applyCommittedEntries();
628
- }
629
- }
630
- }
631
- applyCommittedEntries() {
632
- while (this.state.lastApplied < this.state.commitIndex) {
633
- this.state.lastApplied++;
634
- const entry = this.state.log[this.state.lastApplied - 1];
635
- if (entry) {
636
- this.emit('entry_committed', entry);
637
- // Resolve command promises
638
- for (const [id, resolve] of this.commandQueue.entries()) {
639
- resolve(true);
640
- this.commandQueue.delete(id);
641
- }
642
- }
643
- }
644
- }
645
- // ============================================================================
646
- // Private Methods - Timers
647
- // ============================================================================
648
- resetElectionTimer() {
649
- this.clearElectionTimer();
650
- const timeout = this.config.electionTimeoutMin +
651
- Math.random() * (this.config.electionTimeoutMax - this.config.electionTimeoutMin);
652
- this.electionTimer = setTimeout(() => {
653
- if (this.state.state !== 'leader') {
654
- this.becomeCandidate();
655
- }
656
- }, timeout);
657
- }
658
- clearElectionTimer() {
659
- if (this.electionTimer) {
660
- clearTimeout(this.electionTimer);
661
- this.electionTimer = null;
662
- }
663
- }
664
- clearHeartbeatTimer() {
665
- if (this.heartbeatTimer) {
666
- clearInterval(this.heartbeatTimer);
667
- this.heartbeatTimer = null;
668
- }
669
- }
670
- // ============================================================================
671
- // Private Methods - Byzantine Fault Tolerance
672
- // ============================================================================
673
- setupBFT() {
674
- // Generate keypair (simplified - use real crypto in production)
675
- this.privateKey = crypto.randomBytes(32).toString('hex');
676
- const publicKey = crypto.createHash('sha256').update(this.privateKey).digest('hex');
677
- this.publicKeys.set(this.config.nodeId, publicKey);
678
- }
679
- signData(data) {
680
- if (!this.privateKey)
681
- return '';
682
- const message = JSON.stringify(data);
683
- return crypto.createHmac('sha256', this.privateKey).update(message).digest('hex');
684
- }
685
- verifySignature(data, signature) {
686
- if (!signature)
687
- return false;
688
- // In real implementation, verify with sender's public key
689
- return true;
690
- }
691
- // ============================================================================
692
- // Private Methods - Gossip Protocol
693
- // ============================================================================
694
- startGossipProtocol() {
695
- this.gossipInterval = setInterval(() => {
696
- this.gossipToRandomPeers();
697
- }, 1000); // Gossip every second
698
- }
699
- stopGossipProtocol() {
700
- if (this.gossipInterval) {
701
- clearInterval(this.gossipInterval);
702
- this.gossipInterval = null;
703
- }
704
- }
705
- gossipToRandomPeers() {
706
- const message = {
707
- type: 'state',
708
- nodeId: this.config.nodeId,
709
- data: {
710
- state: this.state.state,
711
- term: this.state.currentTerm,
712
- logLength: this.state.log.length,
713
- },
714
- timestamp: Date.now(),
715
- };
716
- // Sign message for BFT
717
- if (this.config.byzantineTolerance) {
718
- message.signature = this.signData(message);
719
- }
720
- this.emit('gossip', message);
721
- }
722
- gossipCRDTUpdate(key, state) {
723
- const message = {
724
- type: 'metadata',
725
- nodeId: this.config.nodeId,
726
- data: { key, state },
727
- timestamp: Date.now(),
728
- };
729
- if (this.config.byzantineTolerance) {
730
- message.signature = this.signData(message);
731
- }
732
- this.emit('gossip', message);
733
- }
734
- // ============================================================================
735
- // Private Methods - Lock Monitoring
736
- // ============================================================================
737
- startLockMonitoring() {
738
- this.lockCheckInterval = setInterval(() => {
739
- this.checkExpiredLocks();
740
- const deadlocks = this.detectDeadlocks();
741
- if (deadlocks.length > 0) {
742
- this.emit('deadlock_detected', { deadlocks });
743
- }
744
- }, 5000); // Check every 5 seconds
745
- }
746
- stopLockMonitoring() {
747
- if (this.lockCheckInterval) {
748
- clearInterval(this.lockCheckInterval);
749
- this.lockCheckInterval = null;
750
- }
751
- }
752
- checkExpiredLocks() {
753
- const now = Date.now();
754
- for (const [key, lock] of this.locks.entries()) {
755
- if (lock.expiresAt < now) {
756
- this.locks.delete(key);
757
- this.emit('lock_expired', { key, holder: lock.holder });
758
- }
759
- }
760
- }
761
- }
762
- //# sourceMappingURL=RaftConsensus.js.map