import { type Worker } from "node:cluster"; import { EventEmitter } from "node:events"; import { type Server as HttpServer } from "node:http"; import { ServiceRegistry } from "../registry/ServiceRegistry.js"; import type { ScaleRecommendation } from "../scaling/ScaleAdvisor.js"; import { ScaleAdvisor } from "../scaling/ScaleAdvisor.js"; import { AlertSink } from "./AlertSink.js"; import type { Channel, NormalizedConfig, NormalizedService, ProcessGroup } from "./config.js"; import { type RegistryMode as RegistryModeValue, type ServiceType as ServiceTypeValue } from "./config-enums.js"; import { DirectMessageBus } from "./DirectMessageBus.js"; import { ThreadAllocator } from "./ThreadAllocator.js"; interface WorkerMapEntry { groupName: string; services: string[]; workerId: number; } interface RestartHistory { count: number; firstRestart: number; lastRestart: number; } interface MetricsSnapshot { expected: Set; chunks: string[]; timer: ReturnType; finish: () => void; } interface PortTarget { port: number; purpose: string; } interface ParsedAddress { host: string; port: number; } interface EndpointEntry { host: string; port?: number; remote: boolean; uds?: string | null; group?: string; } export interface StatusGroup { group: string; services: { name: string; type: ServiceTypeValue; port: number | null; }[]; workers: number; pids: number[]; } interface StatusResult { supervisorPid: number; uptime: number; totalCpus: number; nodeId: string; host: string; registryMode: RegistryModeValue; processGroups: StatusGroup[]; channels: Channel[]; totalProcesses: number; totalServices: number; remoteServices: number; portsUsed: (number | null)[]; messageBus: Record; topology: Record; scalingRecommendations: ScaleRecommendation[]; hostMode?: boolean; domain?: string | null; projects?: Record; platformMode?: boolean; } interface SupervisorOptions { cpus?: number; reserved?: number; registryMode?: RegistryModeValue; host?: string; httpBasePort?: number; evaluationIntervalMs?: number; } interface ForgeWorkerMessage { type: string; requestId?: string; error?: string; message?: string; port?: number; metrics?: string; [key: string]: unknown; } interface ForgePlugin { name?: string; validate?: () => Promise; env?: () => Record; } /** * Supervisor v2 * * Key differences from v1: * * - Understands service types (edge/internal/background) * - Only edge services get HTTP servers * - Colocated services share a process (same event loop) * - Channels are dependency-based, not full mesh * - Thread allocation is per process group, not per service */ export declare class Supervisor extends EventEmitter { config: NormalizedConfig; services: Record; groups: Record; channels: Channel[]; options: SupervisorOptions; allocator: ThreadAllocator; messageBus: DirectMessageBus; registry: ServiceRegistry; scaleAdvisor: ScaleAdvisor; alertSink: AlertSink; plugins: ForgePlugin[]; _pluginEnv: Record; _failedPlugins: Set; workerMap: Map; groupWorkers: Map; allocation: Map; _metricsServer: HttpServer | null; _shuttingDown: boolean; _restartHistory: Map; _scalingDown: Set; _pendingRestarts: Map>; _killTimers: Map>; _restartWarningTimes: Map; _endpointTempFile: string | null; _sitesTempFile: string | null; _metricsRequestSeq: number; _pendingMetricsSnapshots: Map; _groupReadyWorkers: Map>; _groupReadyLogged: Set; _nextWorkerIndex: Record; _heartbeatInterval: ReturnType | null; _lastHeartbeat: Map; _workersReady: Map; _workerRestartCount: number; _workerErrorGuards: WeakSet; _cachedEndpointJson: string | undefined; _pidFilePath: string | null; constructor(config: NormalizedConfig, options?: SupervisorOptions); start(): Promise; /** * Allocate threads per process group. * * Each group gets threads based on the highest weight of its member * services. Colocated services share their group's allocation. */ _allocateGroups(): void; /** * Fork a worker for a process group. * * The worker will load ALL services in the group within a single * process. Colocated services communicate via direct function calls. */ _forkGroupWorker(groupName: string, group: ProcessGroup, workerIndex: number): Worker; _attachWorkerErrorGuard(worker: Worker, groupName: string, serviceNames: string[], workerIndex: number): void; _sendWorkerMessage(worker: Worker, message: Record, label?: string): boolean; _handleWorkerMessage(worker: Worker, msg: ForgeWorkerMessage): void; _mergePrometheusExpositions(expositions: string[]): string; _collectMetricsSnapshot(timeoutMs?: number): Promise; _handleWorkerExit(worker: Worker, code: number, signal: string): void; _startupPortsToCheck(): PortTarget[]; _isPortAvailable(port: number, host?: string): Promise; _assertStartupPortsAvailable(): Promise; scale(groupName: string, newCount: number): Promise; /** * H-5: Start heartbeat monitor — checks worker health every 30s. * Warns after 60s of silence, kills after 90s. */ _startHeartbeatMonitor(): void; _stopHeartbeatMonitor(): void; shutdown(): Promise; _startMetricsServer(): Promise; _status(): StatusResult; /** * Build endpoint map for workers. * * Maps each service to { host, port, remote } or an array of endpoints * for multi-instance services. Remote services get their address parsed * into host/port. Local services get host: '127.0.0.1'. */ _buildEndpointMap(): Record; /** * Parse a service address string into host/port. * Supports: "http://host:port", "host:port", and other URL schemes */ _parseAddress(address: string | undefined, serviceName: string): ParsedAddress | null; _printAllocation(): void; _printTopology(): void; _banner(): string; } export {}; //# sourceMappingURL=Supervisor.d.ts.map