/** * Allocation service — owns the lifecycle a compute allocation has *before* and * *around* the cluster registry: submit a job, follow it through the queue, and * correlate the client-server's registration (by one-time token) back to the * allocation. Once correlated, the allocation is a normal registered server and * kernels run on it through the existing cluster path. * * Phase-1 MVP: in-memory allocations, direct transport (no SSH tunnel — not * needed where compute↔login is directly reachable). */ import type { Scheduler, JobSpec } from './types'; import { type LaunchContext } from './job-template'; export type AllocationState = 'pending' | 'running' | 'active' | 'ended' | 'failed' | 'cancelled'; export interface Allocation { id: string; jobId?: string; token: string; spec: JobSpec; state: AllocationState; serverId?: string; nodes?: string[]; reason?: string; createdAt: number; walltimeEndsAt?: number; } export declare class AllocationService { private scheduler; private ctx; private allocations; private pollTimer; private enabled; private lastPollAt; private lostListenerRegistered; init(scheduler: Scheduler, ctx: LaunchContext): void; /** Poll immediately (debounced to 2s so error bursts don't hammer squeue). */ pollNow(): void; private stateFile; /** * Allocations survive head-server restarts: persisted on every change, * reloaded on init. A reloaded 'active' allocation is demoted to 'running' * with its serverId cleared — the registry is empty after a restart, and * the compute node's client-server re-registers itself (heartbeat -> 404 * -> re-register with its allocation token) within ~30s, at which point * poll() re-correlates and promotes it back to 'active'. The SLURM job * itself is re-checked by jobId on the next poll, so jobs that died while * we were down are marked ended/failed instead of lingering. */ private persist; private loadPersisted; /** Pick the poll cadence from what we're actually waiting for. */ private nextPollDelay; private scheduleNextPoll; isEnabled(): boolean; getScheduler(): Scheduler | null; getLaunchContext(): LaunchContext | null; list(): Allocation[]; get(id: string): Allocation | undefined; create(spec: JobSpec): Promise; cancel(id: string): Promise; private poll; /** Last few lines of an allocation's job log (bounded read), or null. */ private readLogTail; shutdown(): void; } export declare const allocationService: AllocationService;