From 71e2b654bd69815e5fa83b0f407c8bdead5b5599 Mon Sep 17 00:00:00 2001 From: Jonas Pacheco Date: Wed, 8 Apr 2026 12:03:55 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20resolve=20race=20condition=20entre=20Ker?= =?UTF-8?q?nel=20e=20Casa=20de=20M=C3=A1quinas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move início do Kernel ANTES do servidor HTTP (porta 5000) - Adiciona retry com exponential backoff na consulta ao Registry - Garante que Registry esteja pronto antes de receber requisições Fixes: Casa de Máquinas mostrava 0/0 serviços porque API chamava Registry antes do Kernel iniciar na porta 5001 --- server/engine-room/routes.ts | 24 ++++++++++++++++++++---- server/index.ts | 35 ++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/server/engine-room/routes.ts b/server/engine-room/routes.ts index 0ffc46f..b5b9afa 100644 --- a/server/engine-room/routes.ts +++ b/server/engine-room/routes.ts @@ -10,7 +10,23 @@ import http from "http"; // Consulta Registry do Kernel para serviços descobertos // Usa http.get em vez de fetch por causa de problemas com loopback no Node.js -async function fetchRegistryServices(): Promise { +// Implementa retry com backoff para maior resiliência +async function fetchRegistryServicesWithRetry(maxRetries = 3, delay = 500): Promise { + for (let attempt = 1; attempt <= maxRetries; attempt++) { + const result = await fetchRegistryServicesOnce(); + if (result !== null) { + return result; + } + if (attempt < maxRetries) { + console.log(`[Engine Room] Tentativa ${attempt} falhou, aguardando ${delay}ms...`); + await new Promise(r => setTimeout(r, delay)); + delay *= 2; // Exponential backoff + } + } + return null; +} + +async function fetchRegistryServicesOnce(): Promise { return new Promise((resolve) => { const options = { hostname: '127.0.0.1', @@ -90,7 +106,7 @@ export function registerEngineRoomRoutes(app: Express): void { return res.status(401).json({ error: "Not authenticated" }); } - const registryServices = await fetchRegistryServices(); + const registryServices = await fetchRegistryServicesWithRetry(); const engines: any[] = []; if (registryServices && registryServices.length > 0) { @@ -131,7 +147,7 @@ export function registerEngineRoomRoutes(app: Express): void { // Lista de engines - APENAS do Registry app.get("/api/engine-room/engines", async (_req: Request, res: Response) => { - const registryServices = await fetchRegistryServices(); + const registryServices = await fetchRegistryServicesWithRetry(); const engines = registryServices?.map(mapRegistryToEngine) || []; res.json({ @@ -233,7 +249,7 @@ export function registerEngineRoomRoutes(app: Express): void { return res.status(401).json({ error: "Not authenticated" }); } - const registryServices = await fetchRegistryServices(); + const registryServices = await fetchRegistryServicesWithRetry(); const service = registryServices?.find((s: any) => s.id === req.params.name || s.name === req.params.name); if (!service) { diff --git a/server/index.ts b/server/index.ts index 15381ca..7476195 100644 --- a/server/index.ts +++ b/server/index.ts @@ -395,24 +395,8 @@ export function log(message: string, source = "express") { await setupVite(httpServer, app); } - // ALWAYS serve the app on the port specified in the environment variable PORT - // Other ports are firewalled. Default to 5000 if not specified. - // this serves both the API and the client. - // It is the only port that is not firewalled. - const port = parseInt(process.env.PORT || "5000", 10); - httpServer.listen( - { - port, - host: "0.0.0.0", - reusePort: true, - }, - () => { - log(`serving on port ${port}`); - }, - ); - // Inicia Arcadia Kernel (Dashboard porta 5001) - Semana 3 - // Só inicia se KERNEL_ENABLED estiver setado + // Inicia ANTES do servidor HTTP para garantir que o Registry esteja pronto if (process.env.KERNEL_ENABLED === 'true') { try { const kernel = new ArcadiaKernel({ @@ -427,4 +411,21 @@ export function log(message: string, source = "express") { } else { log('Kernel desabilitado (set KERNEL_ENABLED=true para ativar)'); } + + // ALWAYS serve the app on the port specified in the environment variable PORT + // Other ports are firewalled. Default to 5000 if not specified. + // this serves both the API and the client. + // It is the only port that is not firewalled. + // INICIA DEPOIS do Kernel para garantir que o Registry esteja pronto + const port = parseInt(process.env.PORT || "5000", 10); + httpServer.listen( + { + port, + host: "0.0.0.0", + reusePort: true, + }, + () => { + log(`serving on port ${port}`); + }, + ); })();