/** * `createIsolatePool` — a lazy, keyed pool of {@link Isolate}s. * * Use it when many independent workloads each want their own isolate (one per * tenant, per conversation, per session, per sandboxed-mutation name, …) and * you'd rather not roll the lifecycle yourself. The pool spawns lazily on * first use of a key, reuses across subsequent calls to the same key, evicts * idle keys when the size cap fills, recycles after a configured call count * to bound JSC heap creep, and survives isolate self-termination (timeout / * memory) by re-spawning transparently on the next call. * * Two callers already need this: * * - `@absolutejs/sync`'s `sandboxedHandler` — one isolate per mutation name. * - The future `@absolutejs/ai` `codeExecutionTool` — one isolate per * conversation, so successive turns reuse JIT'd code + warm references. * * Both used to roll their own lazy-spawn-by-key map. This factors the pattern. */ import type { Isolate, IsolateOptions } from "./types"; export type IsolatePoolOptions = { /** * Per-isolate options passed to {@link createIsolate}. Same for every key * — a pool is "many isolates with the same shape." Use multiple pools * if you need different shapes (different memoryLimit / harden / etc). */ isolate?: IsolateOptions; /** * Max number of distinct keys held at once. When the cap is full and a * new key arrives, the least-recently-used idle key is evicted (its * isolate is disposed). Default 32. */ maxSize?: number; /** * If a key isn't used for this long, the pool disposes its isolate and * forgets the key. Default 60_000 ms. Set to `0` to disable idle * eviction (only the LRU cap recycles in that mode). */ idleMs?: number; /** * Recycle an isolate after this many `run()` calls — dispose + respawn * on the next call. Bounds the per-context heap creep we documented in * sync's `sandbox.ts` (~2 MB residual per call). Default `Infinity` * (no recycle). */ recycleAfter?: number; /** * Background sweep interval for idle eviction. Default 5000 ms. The * sweep only runs when the pool is non-empty. */ sweepIntervalMs?: number; }; /** * Operator-shaped metrics surfaced by {@link IsolatePool.metrics} (0.10.0+). * Counters + point-in-time fields a PaaS host scrapes on an interval to * attribute per-tenant cost and detect a runaway. */ export type IsolatePoolMetrics = { /** Date.now() when this snapshot was taken. */ at: number; /** Active cached keys right now. */ size: number; /** Active runs that haven't returned yet (sum of `inFlight` across entries). */ inFlight: number; /** Cumulative spawns (first-use + post-recycle respawn) since pool start. */ spawns: number; /** Cumulative idle-window evictions since pool start. */ idleEvictions: number; /** Cumulative LRU evictions since pool start. */ lruEvictions: number; /** Cumulative recycles since pool start (`run()` counts crossing `recycleAfter`). */ recycles: number; /** True when the pool is draining (refusing new keys). */ draining: boolean; }; /** A keyed pool of isolates. */ export type IsolatePool = { /** * Get the isolate for `key`, run `fn` with it, and return whatever `fn` * returns. Spawns on first use of the key; subsequent calls to the same * key reuse the same isolate. Concurrent `run` calls to the same key * share the isolate but each gets its own Context (the body of `fn` * controls that). * * If the isolate self-terminated since the last call (timeout / memory), * the pool transparently respawns before invoking `fn`. */ run: (key: string, fn: (isolate: Isolate) => Promise) => Promise; /** Approximate active size — number of cached keys. */ size: () => number; /** * Operator-shaped metrics — point-in-time + cumulative counters since * pool start. What a PaaS host scrapes for cost attribution. Added in * 0.10.0. */ metrics: () => IsolatePoolMetrics; /** * Begin draining: refuse `run` on new keys (existing cached keys keep * working). For graceful shard shutdown — wait for `size()` to reach 0 * then call `dispose()`. Added in 0.10.0. */ drain: () => void; /** Dispose every isolate and stop the sweep. Idempotent. */ dispose: () => Promise; }; export declare const createIsolatePool: (options?: IsolatePoolOptions) => IsolatePool;