/** * Arcadia Kernel - Entry Point * Sistema nativo de gerenciamento de serviços * * V3.0 - Adicionado Service Registry + Docker Discovery */ import { readFileSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import { ProcessManager } from './core/ProcessManager'; import { HealthMonitor } from './core/HealthMonitor'; import { LogAggregator } from './core/LogAggregator'; import { DashboardServer } from './dashboard/DashboardServer'; import { ServiceConfig, ServiceState } from './types'; // NOVO: Service Registry e Discovery import { ServiceRegistry } from './registry/ServiceRegistry'; import { DockerDiscovery } from './discovery/DockerDiscovery'; import { StaticDiscovery } from './discovery/StaticDiscovery'; import { CoolifyDiscovery } from './discovery/CoolifyDiscovery'; import { XOSDiscovery } from './discovery/XOSDiscovery'; import { RegistryConfig, RegisteredService } from './registry/types'; // Suporte a ESM e CommonJS (build do Docker) const __dirname = (() => { try { return dirname(fileURLToPath(import.meta.url)); } catch { return join(process.cwd(), 'server', 'kernel'); } })(); export interface KernelOptions { configPath?: string; dashboard?: { enabled?: boolean; port?: number; host?: string; }; autoStart?: boolean; // NOVO: Opções do Service Registry registry?: { enabled?: boolean; config?: Partial; }; } export class ArcadiaKernel { public processManager: ProcessManager; public healthMonitor: HealthMonitor; public logAggregator: LogAggregator; public dashboard?: DashboardServer; // NOVO: Service Registry public serviceRegistry?: ServiceRegistry; private options: Required; private services: ServiceConfig[] = []; private started = false; constructor(options: KernelOptions = {}) { this.options = { configPath: join(__dirname, 'config', 'services.json'), dashboard: { enabled: true, port: 5001, host: '0.0.0.0', }, autoStart: false, // NOVO: Registry ativado por padrão registry: { enabled: true, config: { enableAutoDiscovery: true, discoveryInterval: 30000, healthCheckInterval: 15000, }, }, ...options, }; // Inicializa componentes existentes this.logAggregator = new LogAggregator({ maxLines: 10000 }); this.processManager = new ProcessManager({ onLog: (entry) => this.logAggregator.add(entry), onStateChange: (serviceId, state) => { console.log(`[Kernel] ${serviceId}: ${state.status}`); }, onHealthChange: (serviceId, health) => { console.log(`[Kernel] ${serviceId} health: ${health}`); }, }); this.healthMonitor = new HealthMonitor({ onHealthChange: (serviceId, health, error) => { this.processManager.setHealth(serviceId, health); if (error) { console.log(`[Kernel] ${serviceId} health error: ${error}`); } }, }); // NOVO: Inicializa Service Registry se habilitado if (this.options.registry.enabled) { this.serviceRegistry = new ServiceRegistry({ config: this.options.registry.config, discoveryProviders: [ new StaticDiscovery(), // Descoberta via DNS interno new CoolifyDiscovery({ // Descoberta via API Coolify baseUrl: 'https://coolify.onboardbi.com.br', token: process.env.COOLIFY_API_TOKEN || '', }), new XOSDiscovery(), // Descoberta de serviços XOS (filas, integrações) new DockerDiscovery({ networkName: 'arcadia' }), // Fallback ], }); // Escuta eventos do registry this.serviceRegistry.on('event', (event) => { console.log(`[Registry] ${event.type}: ${event.serviceId}`); }); } // Carrega configurações this.loadConfig(); } /** * Inicia o Kernel */ async start(): Promise { if (this.started) { return; } console.log('[Kernel] Iniciando Arcadia Kernel...'); console.log(`[Kernel] ${this.services.length} serviços configurados (services.json)`); // Registra serviços no ProcessManager for (const config of this.services) { this.processManager.registerService(config); } // NOVO: Inicia Service Registry if (this.serviceRegistry) { await this.serviceRegistry.start(); } // Inicia Dashboard if (this.options.dashboard.enabled) { this.dashboard = new DashboardServer( this.processManager, this.healthMonitor, this.logAggregator, this.serviceRegistry, // Passa o Registry pro Dashboard { port: this.options.dashboard.port, host: this.options.dashboard.host, } ); await this.dashboard.start(); } // Auto-start serviços if (this.options.autoStart) { console.log('[Kernel] Auto-iniciando serviços...'); await this.processManager.startAll(true); // Inicia health monitoring para serviços em execução for (const state of this.processManager.getAllStates()) { if (state.status === 'running') { this.healthMonitor.startMonitoring(state.config.id, state); } } } this.started = true; console.log('[Kernel] Kernel iniciado com sucesso!'); // Eventos de shutdown this.setupShutdownHandlers(); } /** * Para o Kernel */ async stop(): Promise { if (!this.started) { return; } console.log('[Kernel] Parando Kernel...'); // NOVO: Para Service Registry this.serviceRegistry?.stop(); // Para health monitor this.healthMonitor.stopAll(); // Para todos os serviços await this.processManager.stopAll(true); // Para dashboard await this.dashboard?.stop(); this.started = false; console.log('[Kernel] Kernel parado.'); } /** * Retorna se o kernel está rodando */ isRunning(): boolean { return this.started; } /** * NOVO: Retorna estatísticas combinadas (ProcessManager + Registry) */ getStats(): { processManager: any; registry: any } { return { processManager: { total: this.services.length, states: this.processManager.getAllStates(), }, registry: this.serviceRegistry?.getStats(), }; } /** * NOVO: Lista serviços descobertos (via Registry) */ getDiscoveredServices(): RegisteredService[] { return this.serviceRegistry?.getServices() || []; } /** * Carrega configurações dos serviços */ private loadConfig(): void { try { const configData = readFileSync(this.options.configPath, 'utf-8'); const config = JSON.parse(configData); this.services = config.services || []; } catch (error) { console.error('[Kernel] Erro ao carregar config:', error); this.services = []; } } /** * Configura handlers de shutdown */ private setupShutdownHandlers(): void { const shutdown = async (signal: string) => { console.log(`\n[Kernel] Sinal ${signal} recebido. Desligando...`); await this.stop(); process.exit(0); }; process.on('SIGTERM', () => shutdown('SIGTERM')); process.on('SIGINT', () => shutdown('SIGINT')); process.on('uncaughtException', (error) => { console.error('[Kernel] Uncaught Exception:', error); }); process.on('unhandledRejection', (reason) => { console.error('[Kernel] Unhandled Rejection:', reason); }); } } // Exporta componentes individuais export { ProcessManager } from './core/ProcessManager'; export { HealthMonitor } from './core/HealthMonitor'; export { LogAggregator } from './core/LogAggregator'; export { DashboardServer } from './dashboard/DashboardServer'; export { KernelWebSocket } from './websocket/KernelWebSocket'; export { createKernelRoutes } from './api/routes'; // NOVO: Exports do Registry e Discovery export { ServiceRegistry } from './registry/ServiceRegistry'; export { DockerDiscovery } from './discovery/DockerDiscovery'; export type { RegisteredService, ServiceFilter, RegistryEvent, DiscoverySource, ServiceCategory, } from './registry/types'; export * from './types'; // Entry point para execução direta try { if (import.meta.url && import.meta.url === `file://${process.argv[1]}`) { const kernel = new ArcadiaKernel({ dashboard: { enabled: true, port: 5001 }, autoStart: true, }); kernel.start().catch((error) => { console.error('[Kernel] Falha ao iniciar:', error); process.exit(1); }); } } catch { // No build CommonJS, o Kernel é iniciado pelo server/index.ts }