mcp-hub-009: Graceful backend failure — JSON-RPC error responses and session cleanup

This commit is contained in:
Agent 2026-03-13 11:00:43 +00:00
parent 050c63e8d3
commit aa78585a45
3 changed files with 52 additions and 4 deletions

View file

@ -3,9 +3,21 @@ const registry = require('./backend-registry');
const pendingRequests = new Map();
function sendToBackend(serviceId, message, clientSessionId) {
function sendToBackend(serviceId, message, clientSessionId, sessions) {
const ws = registry.get(serviceId);
if (!ws) return null;
if (!ws) {
if (sessions && message.id !== undefined && message.id !== null) {
const session = sessions.get(clientSessionId);
if (session) {
session.res.write('event: message\ndata: ' + JSON.stringify({
jsonrpc: '2.0',
id: message.id,
error: { code: -32603, message: 'Backend unavailable' }
}) + '\n\n');
}
}
return null;
}
const requestId = uuidv4();
pendingRequests.set(requestId, { serviceId, clientSessionId });
@ -53,4 +65,37 @@ function handleBackendMessage(serviceId, data, sessions) {
}
}
module.exports = { sendToBackend, handleBackendMessage };
function cleanupBackend(serviceId, sessions) {
// Clean up pending requests for this backend
for (const [requestId, pending] of pendingRequests) {
if (pending.serviceId === serviceId) {
const session = sessions.get(pending.clientSessionId);
if (session) {
// Write error notification event
session.res.write('event: message\ndata: ' + JSON.stringify({
jsonrpc: '2.0',
id: null,
error: { code: -32603, message: 'Backend disconnected' }
}) + '\n\n');
}
pendingRequests.delete(requestId);
}
}
// Clean up active SSE sessions for this backend
for (const [clientSessionId, session] of sessions) {
if (session.serviceId === serviceId) {
// Write final error event
session.res.write('event: message\ndata: ' + JSON.stringify({
jsonrpc: '2.0',
id: null,
error: { code: -32603, message: 'Backend disconnected' }
}) + '\n\n');
// End the response
session.res.end();
sessions.delete(clientSessionId);
}
}
}
module.exports = { sendToBackend, handleBackendMessage, cleanupBackend };

View file

@ -42,7 +42,7 @@ router.post('/:serviceId/message', (req, res) => {
return res.status(502).json({ error: 'backend not connected' });
}
relay.sendToBackend(serviceId, req.body, sessionId);
relay.sendToBackend(serviceId, req.body, sessionId, sessions);
return res.status(202).json({ status: 'accepted' });
});

View file

@ -78,6 +78,9 @@ function setupWsServer(httpServer) {
if (pingTimer) clearInterval(pingTimer);
if (authenticated && serviceId) {
registry.unregister(serviceId);
const { cleanupBackend } = require('./relay');
const { sessions } = require('./routes/mcp-proxy');
cleanupBackend(serviceId, sessions);
}
});