fix: resolve race condition entre Kernel e Casa de Máquinas
- 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
This commit is contained in:
parent
ea58a45ea1
commit
71e2b654bd
|
|
@ -10,7 +10,23 @@ import http from "http";
|
||||||
|
|
||||||
// Consulta Registry do Kernel para serviços descobertos
|
// Consulta Registry do Kernel para serviços descobertos
|
||||||
// Usa http.get em vez de fetch por causa de problemas com loopback no Node.js
|
// Usa http.get em vez de fetch por causa de problemas com loopback no Node.js
|
||||||
async function fetchRegistryServices(): Promise<any[] | null> {
|
// Implementa retry com backoff para maior resiliência
|
||||||
|
async function fetchRegistryServicesWithRetry(maxRetries = 3, delay = 500): Promise<any[] | null> {
|
||||||
|
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<any[] | null> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const options = {
|
const options = {
|
||||||
hostname: '127.0.0.1',
|
hostname: '127.0.0.1',
|
||||||
|
|
@ -90,7 +106,7 @@ export function registerEngineRoomRoutes(app: Express): void {
|
||||||
return res.status(401).json({ error: "Not authenticated" });
|
return res.status(401).json({ error: "Not authenticated" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const registryServices = await fetchRegistryServices();
|
const registryServices = await fetchRegistryServicesWithRetry();
|
||||||
const engines: any[] = [];
|
const engines: any[] = [];
|
||||||
|
|
||||||
if (registryServices && registryServices.length > 0) {
|
if (registryServices && registryServices.length > 0) {
|
||||||
|
|
@ -131,7 +147,7 @@ export function registerEngineRoomRoutes(app: Express): void {
|
||||||
|
|
||||||
// Lista de engines - APENAS do Registry
|
// Lista de engines - APENAS do Registry
|
||||||
app.get("/api/engine-room/engines", async (_req: Request, res: Response) => {
|
app.get("/api/engine-room/engines", async (_req: Request, res: Response) => {
|
||||||
const registryServices = await fetchRegistryServices();
|
const registryServices = await fetchRegistryServicesWithRetry();
|
||||||
const engines = registryServices?.map(mapRegistryToEngine) || [];
|
const engines = registryServices?.map(mapRegistryToEngine) || [];
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
|
|
@ -233,7 +249,7 @@ export function registerEngineRoomRoutes(app: Express): void {
|
||||||
return res.status(401).json({ error: "Not authenticated" });
|
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);
|
const service = registryServices?.find((s: any) => s.id === req.params.name || s.name === req.params.name);
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
|
|
|
||||||
|
|
@ -395,24 +395,8 @@ export function log(message: string, source = "express") {
|
||||||
await setupVite(httpServer, app);
|
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
|
// 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') {
|
if (process.env.KERNEL_ENABLED === 'true') {
|
||||||
try {
|
try {
|
||||||
const kernel = new ArcadiaKernel({
|
const kernel = new ArcadiaKernel({
|
||||||
|
|
@ -427,4 +411,21 @@ export function log(message: string, source = "express") {
|
||||||
} else {
|
} else {
|
||||||
log('Kernel desabilitado (set KERNEL_ENABLED=true para ativar)');
|
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}`);
|
||||||
|
},
|
||||||
|
);
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue