import { spawn, type ChildProcess } from 'node:child_process'; import { type OxigraphMemoryLimits } from './oxigraph-launch-strategy.js'; import { type OxigraphStoreOwnership } from './oxigraph-store-launch.js'; import { type OxigraphStoreOwnershipInput } from './oxigraph-store-ownership.js'; import { type CgroupOomSnapshot } from './oxigraph-memory.js'; export interface OxigraphServerIo { spawn: typeof spawn; fetch: typeof globalThis.fetch; /** Signal a listener PID after ownership has been re-verified. Injectable for safety tests. */ killProcess: typeof process.kill; /** * Resolve the child/descendant PID that owns the listen socket (not merely * that something on the port returns HTTP 200). */ findListenOwnerPid: (child: ChildProcess, port: number, host: string, ownership?: 'child-only' | 'process-tree') => Promise; /** Best-effort cgroup OOM snapshot (dir + oom_kill) for a live pid. Injectable for tests. */ readCgroupOomSnapshot: (pid: number) => CgroupOomSnapshot | null; /** Best-effort exit-time re-read of oom_kill from a captured cgroup dir. */ readCgroupOomKill: (dir: string) => number | null; } export interface StartOxigraphServerOptions { /** Absolute path to the verified `oxigraph` binary. */ binaryPath: string; /** RocksDB storage directory (`--location`). */ location: string; /** Bind host. Always loopback in production; overridable for tests. */ host?: string; /** Bind port. */ port: number; log?: (msg: string) => void; /** Total time to wait for the server to answer before failing start. */ readyTimeoutMs?: number; /** Native Oxigraph query timeout (`oxigraph serve --timeout-s`). */ queryTimeoutS?: number; /** Poll interval while waiting for readiness. */ readyIntervalMs?: number; /** Grace period between SIGTERM and SIGKILL on stop. */ stopGraceMs?: number; /** * Base of the automatic WAL-aware readiness deadline (GH#1400). Production * default is DEFAULT_READY_TIMEOUT_MS; exposed as a test seam. Deliberately * NOT read from `store.options` — operators configure `readyTimeoutMs`, * which overrides the automatic sizing entirely. */ autoReadyBaseTimeoutMs?: number; /** Progress-log cadence while a retained WAL is opening. Test seam. */ progressLogIntervalMs?: number; /** Base delay for restart backoff after an unexpected crash. */ restartBackoffBaseMs?: number; /** Cap for restart backoff. */ restartBackoffMaxMs?: number; /** Optional finite limits for an isolated systemd user scope (Linux only). */ memoryLimits?: OxigraphMemoryLimits; /** Runtime platform. Injectable so command construction is portable in tests. */ platform?: NodeJS.Platform; /** * Build the store ownership for this start: the orphan reclaim before each * spawn and the owner record of each launch. The default knows only * `binaryPath`; the managed layer builds one with the reclaim catalog of * the binary it resolved, and lifecycle tests supply their own. */ storeOwnership?: (input: OxigraphStoreOwnershipInput) => OxigraphStoreOwnership; io?: Partial; } export interface OxigraphServerHandle { readonly host: string; readonly port: number; readonly queryEndpoint: string; readonly updateEndpoint: string; /** * Terminate an unhealthy managed server and let the existing supervisor * respawn it. Returns false when shutdown/recovery is already in progress; * accepted requests re-verify listener ownership before sending a signal. */ requestRestart(reason: string): boolean; /** Runtime-only recovery state consumed by the managed SPARQL adapter. */ getRecoveryState(): OxigraphRecoveryState; /** Stop the server and prevent further restarts. Idempotent. */ stop(): Promise; /** * Synchronous best-effort SIGTERM for `process.on('exit')` handlers * (which cannot await). Prevents orphaning the server when boot hits a * fatal `process.exit()` after the server started. Idempotent. */ killSync(): void; } export interface OxigraphRecoveryState { recovering: boolean; generation: number; } /** * Spawn and health-check a local Oxigraph server. Resolves once the * server answers an `ASK` probe; rejects if it never becomes ready within * `readyTimeoutMs` (the child is killed first so we don't leak it). */ export declare function startOxigraphServer(opts: StartOxigraphServerOptions): Promise; //# sourceMappingURL=oxigraph-server.d.ts.map