diff --git a/server/kernel/discovery/StaticDiscovery.ts b/server/kernel/discovery/StaticDiscovery.ts new file mode 100644 index 0000000..05a37ac --- /dev/null +++ b/server/kernel/discovery/StaticDiscovery.ts @@ -0,0 +1,176 @@ +/** + * Static Discovery Provider + * Descobre serviços pela rede Docker interna (DNS) + * Arcadia Kernel - Módulo de Service Discovery + */ + +import { DiscoveryProvider, RegisteredService, ServiceCategory } from '../registry/types'; +import { HealthStatus } from '../types'; + +// Lista de serviços Arcádia conhecidos +const ARCADIA_SERVICES = [ + { + id: 'motor-contabil', + name: 'motor-contabil', + displayName: 'Motor Contábil', + type: 'python' as const, + category: 'contabil' as ServiceCategory, + host: 'arcadia-prod-contabil-1', + port: 8003, + capabilities: ['lancamentos', 'dre', 'balancete', 'razao'], + requiresIA: false, + description: 'Contabilidade - Lançamentos, DRE, Balancete, Razão', + }, + { + id: 'motor-bi', + name: 'motor-bi', + displayName: 'Motor BI', + type: 'python' as const, + category: 'bi' as ServiceCategory, + host: 'arcadia-prod-bi-1', + port: 8004, + capabilities: ['sql', 'charts', 'microbi', 'cache'], + requiresIA: true, + iaPolicies: ['bi', 'lgpd'], + description: 'Business Intelligence - SQL, Charts, Micro-BI, Cache', + }, + { + id: 'motor-fiscal', + name: 'motor-fiscal', + displayName: 'Motor Fiscal', + type: 'python' as const, + category: 'fiscal' as ServiceCategory, + host: 'arcadia-prod-fisco-1', + port: 8002, + capabilities: ['nfe', 'nfce', 'ncm', 'cfop', 'cest', 'sefaz'], + requiresIA: true, + iaPolicies: ['fiscal'], + description: 'NF-e/NFC-e - NCMs, CFOPs, CESTs, SEFAZ', + }, + { + id: 'motor-automacao', + name: 'motor-automacao', + displayName: 'Motor Automação', + type: 'python' as const, + category: 'automation' as ServiceCategory, + host: 'arcadia-prod-automation-1', + port: 8005, + capabilities: ['scheduler', 'eventbus', 'workflow'], + requiresIA: true, + iaPolicies: ['automation'], + description: 'Scheduler, Event Bus, Workflow Executor', + }, + { + id: 'servico-embeddings', + name: 'servico-embeddings', + displayName: 'Serviço Embeddings', + type: 'python' as const, + category: 'ai' as ServiceCategory, + host: 'arcadia-prod-embeddings-1', + port: 8001, + capabilities: ['embeddings', 'vectorsearch'], + requiresIA: true, + iaPolicies: ['ai', 'lgpd'], + description: 'Embeddings e Vector Search com pgvector', + }, + { + id: 'metaset-bi', + name: 'metaset-bi', + displayName: 'MetaSet BI', + type: 'java' as const, + category: 'data' as ServiceCategory, + host: 'arcadia-prod-superset-1', + port: 8088, + capabilities: ['dashboards', 'charts', 'sql_lab', 'datasets'], + requiresIA: false, + description: 'Motor de BI - Consultas, Dashboards, Gráficos, Análises', + version: '4.1.0', + }, + { + id: 'motor-comunicacao', + name: 'motor-comunicacao', + displayName: 'Motor Comunicação', + type: 'node' as const, + category: 'communication' as ServiceCategory, + host: 'arcadia-prod-miroflow-1', + port: 8006, + capabilities: ['inbox', 'whatsapp', 'canais'], + requiresIA: true, + iaPolicies: ['communication'], + description: 'Inbox Unificada, Contatos, Threads, Canais', + }, +]; + +export class StaticDiscovery implements DiscoveryProvider { + public readonly name = 'StaticDiscovery'; + + async isAvailable(): Promise { + // Sempre disponível - não depende de Docker + return true; + } + + async discover(): Promise { + const services: RegisteredService[] = []; + const now = new Date(); + + for (const config of ARCADIA_SERVICES) { + try { + // Tenta fazer health check no serviço + const isHealthy = await this.checkHealth(config.host, config.port); + + if (isHealthy) { + services.push({ + id: `static-${config.id}`, + name: config.name, + displayName: config.displayName, + type: config.type, + category: config.category, + description: config.description, + host: config.host, + port: config.port, + endpoint: `http://${config.host}:${config.port}`, + healthCheckPath: '/health', + healthStatus: 'healthy' as HealthStatus, + lastHealthCheck: now, + capabilities: config.capabilities.map(cap => ({ + name: cap, + version: '1.0.0', + endpoints: [`/${cap}`], + })), + requiresIA: config.requiresIA, + iaPolicies: config.iaPolicies, + metadata: { + source: 'static', + discoveredAt: now, + lastUpdated: now, + labels: {}, + }, + enabled: true, + version: config.version, + }); + } + } catch (error) { + // Serviço não respondeu, não adiciona + console.log(`[StaticDiscovery] ${config.displayName} não respondeu`); + } + } + + return services; + } + + private async checkHealth(host: string, port: number): Promise { + try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 3000); + + const response = await fetch(`http://${host}:${port}/health`, { + signal: controller.signal, + }); + + clearTimeout(timeout); + return response.ok; + } catch { + return false; + } + } +} diff --git a/server/kernel/discovery/index.ts b/server/kernel/discovery/index.ts index 5609825..c952514 100644 --- a/server/kernel/discovery/index.ts +++ b/server/kernel/discovery/index.ts @@ -5,3 +5,4 @@ export { DockerDiscovery } from './DockerDiscovery'; export type { DockerDiscoveryOptions } from './DockerDiscovery'; +export { StaticDiscovery } from './StaticDiscovery'; diff --git a/server/kernel/index.ts b/server/kernel/index.ts index 77850d0..160b585 100644 --- a/server/kernel/index.ts +++ b/server/kernel/index.ts @@ -17,6 +17,7 @@ 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 { RegistryConfig, RegisteredService } from './registry/types'; // Suporte a ESM e CommonJS (build do Docker) @@ -103,7 +104,8 @@ export class ArcadiaKernel { this.serviceRegistry = new ServiceRegistry({ config: this.options.registry.config, discoveryProviders: [ - new DockerDiscovery({ networkName: 'arcadia' }), + new StaticDiscovery(), // Descoberta via DNS interno (recomendado) + new DockerDiscovery({ networkName: 'arcadia' }), // Fallback ], });