Files
p2ns/includes/admin/admin-backend/routes/status.js
T
2026-05-27 19:59:45 -04:00

150 lines
5.2 KiB
JavaScript

const url = require('url');
const state = require('../../../infrastructure/state');
const { trackRequest } = require('../../../maintenance/metrics');
const { createErrorResponse } = require('../../../infrastructure/error_handler');
const { metrics } = require('../../../maintenance/metrics');
async function handleStatusRoutes(req, res) {
const urlPath = req.urlPath || new URL(req.url, `https://${req.headers.host}`).pathname;
const method = req.method;
if (method === 'GET' && urlPath === '/api/status') {
try {
const status = {
isMaster: state.isMaster,
isConnected: !!state.dnsPass,
peersCount: state.connectedPeers.size,
pid: process.pid,
isShuttingDown: state.isShuttingDown || false
};
trackRequest('/api/status', true);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(status));
} catch (err) {
trackRequest('/api/status', false);
const errorResponse = createErrorResponse(err, 500);
res.writeHead(errorResponse.statusCode, errorResponse.headers);
res.end(errorResponse.body);
}
return true;
}
if (method === 'POST' && urlPath === '/api/shutdown') {
try {
const { logInfo } = require('../../../infrastructure/logger');
// Send success response before shutting down
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
message: 'Graceful shutdown initiated. Process will exit after cleanup completes.'
}));
// Trigger graceful shutdown after sending response
setTimeout(() => {
logInfo('Admin', 'Initiating graceful shutdown (without cleaning storage)...');
process.emit('SIGTERM');
}, 500); // Small delay to ensure response is sent
} catch (err) {
const errorResponse = createErrorResponse(err, 500);
res.writeHead(errorResponse.statusCode, errorResponse.headers);
res.end(errorResponse.body);
}
return true;
}
if (method === 'GET' && urlPath === '/api/health') {
try {
const query = url.parse(req.url, true).query;
const probeType = query.probe || 'liveness';
const dnsHealthy = !!state.dnsPass && state.dnsPass.opened !== false;
const proxyHealthy = process.env.DISABLE_PROXY_SERVER !== 'true';
const swarmHealthy = state.connectedPeers !== undefined;
const corestoreHealthy = state.dnsPass && state.dnsPass.base && state.dnsPass.base.writable !== undefined;
const hyperswarmHealthy = swarmHealthy;
const dnsServerHealthy = process.env.DISABLE_DNS_SERVER !== 'true';
const httpsServerHealthy = process.env.DISABLE_PROXY_SERVER !== 'true';
const allServicesHealthy = dnsHealthy && proxyHealthy && swarmHealthy && corestoreHealthy && hyperswarmHealthy;
const status = allServicesHealthy ? 'healthy' : 'degraded';
const health = {
status: status,
timestamp: new Date().toISOString(),
uptime: Date.now() - (metrics?.startTime || Date.now()),
probe: probeType,
services: {
dns: {
enabled: dnsServerHealthy,
healthy: dnsHealthy,
initialized: !!state.dnsPass,
details: {
passReady: state.dnsPass?.opened !== false,
domainsCount: state.domainToIPMap?.size || 0
}
},
proxy: {
enabled: httpsServerHealthy,
healthy: proxyHealthy,
details: {
httpsEnabled: process.env.DISABLE_PROXY_SERVER !== 'true',
httpEnabled: process.env.DISABLE_PROXY_SERVER !== 'true'
}
},
swarm: {
healthy: swarmHealthy,
details: {
connectedPeers: state.connectedPeers?.size || 0,
isMaster: state.isMaster || false
}
}
},
dependencies: {
corestore: {
healthy: corestoreHealthy,
details: {
initialized: !!state.dnsPass,
writable: state.dnsPass?.base?.writable || false
}
},
hyperswarm: {
healthy: hyperswarmHealthy,
details: {
connectedPeers: state.connectedPeers?.size || 0
}
}
}
};
if (probeType === 'readiness') {
const ready = allServicesHealthy && state.dnsPass && state.dnsPass.ready;
if (!ready) {
trackRequest('/api/health', false);
res.writeHead(503, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ...health, status: 'not_ready' }));
return true;
}
}
const statusCode = allServicesHealthy ? 200 : 503;
trackRequest('/api/health', allServicesHealthy);
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(health));
} catch (err) {
trackRequest('/api/health', false);
const errorResponse = createErrorResponse(err, 500);
res.writeHead(errorResponse.statusCode, errorResponse.headers);
res.end(errorResponse.body);
}
return true;
}
return false;
}
module.exports = { handleStatusRoutes };