const state = require('../../../infrastructure/state'); const { getConsensusState, getConsensusMetrics, doAutoVotes, invalidateEntriesCache } = require('../../../core/core'); const { logDebug, logError, logInfo } = require('../../../infrastructure/logger'); const { trackRequest } = require('../../../maintenance/metrics'); const { createErrorResponse } = require('../../../infrastructure/error_handler'); const { broadcast } = require('../websocket'); async function handleConsensusRoutes(req, res) { const urlPath = req.urlPath || new URL(req.url, `https://${req.headers.host}`).pathname; const method = req.method; const url = new URL(req.url, `https://${req.headers.host}`); // GET /api/consensus/metrics - Get consensus metrics // Check this BEFORE the domain route to avoid matching "metrics" as a domain if (method === 'GET' && urlPath === '/api/consensus/metrics') { try { trackRequest('/api/consensus/metrics', true); logDebug('Consensus', 'Getting consensus metrics'); const metrics = getConsensusMetrics(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(metrics)); return true; } catch (err) { logError('Consensus', `Failed to get consensus metrics: ${err.message}`); trackRequest('/api/consensus/metrics', false); createErrorResponse(res, 500, 'Failed to get consensus metrics', err.message); return true; } } // GET /api/consensus/:domain - Get consensus state for a domain const domainMatch = urlPath.match(/^\/api\/consensus\/([^\/]+)$/); if (method === 'GET' && domainMatch) { try { trackRequest('/api/consensus/:domain', true); const domain = decodeURIComponent(domainMatch[1]); logDebug('Consensus', `Getting consensus state for domain: ${domain}`); const consensusState = await getConsensusState(domain); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(consensusState)); return true; } catch (err) { logError('Consensus', `Failed to get consensus state: ${err.message}`); trackRequest('/api/consensus/:domain', false); createErrorResponse(res, 500, 'Failed to get consensus state', err.message); return true; } } // POST /api/consensus/recalculate - Force consensus recalculation if (method === 'POST' && urlPath === '/api/consensus/recalculate') { try { trackRequest('/api/consensus/recalculate', true); logInfo('Consensus', 'Forcing consensus recalculation'); // Invalidate caches invalidateEntriesCache(); // Trigger auto-votes await doAutoVotes(); // Broadcast update broadcast({ type: 'update-database' }); broadcast({ type: 'update-stats' }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true, message: 'Consensus recalculation triggered' })); return true; } catch (err) { logError('Consensus', `Failed to recalculate consensus: ${err.message}`); trackRequest('/api/consensus/recalculate', false); createErrorResponse(res, 500, 'Failed to recalculate consensus', err.message); return true; } } // POST /api/consensus/recalculate/:domain - Force consensus recalculation for specific domain const recalcDomainMatch = urlPath.match(/^\/api\/consensus\/recalculate\/([^\/]+)$/); if (method === 'POST' && recalcDomainMatch) { try { trackRequest('/api/consensus/recalculate/:domain', true); const domain = decodeURIComponent(recalcDomainMatch[1]); logInfo('Consensus', `Forcing consensus recalculation for domain: ${domain}`); // Invalidate caches for this domain invalidateEntriesCache(); // Get all entries and trigger auto-vote for this domain const { getAllEntries, autoVoteForDomain } = require('../../../core/core'); const allEntries = await getAllEntries(); await autoVoteForDomain(domain, allEntries); // Notify other peers to recalculate consensus for this domain if (state.sendConsensusRequest) { state.sendConsensusRequest(domain); } // Broadcast update broadcast({ type: 'update-database' }); broadcast({ type: 'update-stats' }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true, message: `Consensus recalculation triggered for ${domain}` })); return true; } catch (err) { logError('Consensus', `Failed to recalculate consensus for domain: ${err.message}`); trackRequest('/api/consensus/recalculate/:domain', false); createErrorResponse(res, 500, 'Failed to recalculate consensus for domain', err.message); return true; } } // Route not handled by consensus routes return false; } module.exports = { handleConsensusRoutes };