/** * [ref]([ref] / [ref] v1)— E2B 孤儿沙盒回收。 * * 病:server 进程崩溃(SIGKILL/OOM)后 core Runner 的 `destroy()` 不跑,E2B 沙盒按自己的 * timeout 窗继续存活计费;崩溃循环下泄漏累积。create 侧的归属打标早已在 * (`remote-env-e2b.ts` factory:metadata 带 sessionId/taskId,本批补 `semaManaged:"1"`); * 本模块是缺的另一半——回收腿。 * * 判据(全部保守方向,**拿不准恒不杀**——回收是清理型能力,缺席判据=不动作,方向纪律见 * memory `capability-probe-fail-direction`;误杀的代价是杀死一个活任务的手,漏杀的代价只是钱): * a. `metadata.semaManaged !== "1"` → 非我方铸造,provider 侧 query 过滤已排除;防御性重验。 * b. `metadata.taskId` 缺席 → 病态形(factory 恒打标),不杀 + failOpen 留痕。 * c. run 行在场(词 → 类问 `RUN_STATUS_CLASS` 属主,S-221): * 类 live / parked(行还能再动) → 活,跳过; * 类 succeeded / unsuccessful(终局) → 孤儿,kill; * 属主表外的词(类 undefined) → 词表纪律([ref]):不杀 + failOpen(新词先安全后收编)。 * d. 行不存在: * startedAt 距今 < GRACE → create→行落库窗口,跳过(防误杀新沙盒); * ≥ GRACE → 真孤儿,kill(单库 fleet 方向下行跨副本可见)。 * e. `getRun` 抛错 → 不杀 + failOpen(不知道 ≠ 孤儿)。 * * v1 边界([ref] §设计②,发车说明同步):跨部署**异库**共用一把 E2B key 的形不支持—— * 别家沙盒的 taskId 在本库查不到行,超 GRACE 会被误杀;前置=每部署独立 E2B key(本就是推荐姿势)。 * metadata 无跨重启稳定的部署标识可用(instanceId 每 boot 变,恰是要回收上一世代)是结构原因。 * * kill 逐只 try/catch(一只失败不挡其余);list 整体失败由调用方(reaper throttled catch)兜底。 */ import type { Logger } from "../observability/logger.js"; /** create→run 行落库窗口的误杀护栏。非行为表态面,常量不设旋钮(理由:它只需要「远大于一次 * create+首写延迟、远小于沙盒 timeout 窗」,10min 对两端都有量级余量;错设它的运维事故面比 * 它保护的窗口更大)。 */ export declare const E2B_ORPHAN_GRACE_MS: number; /** factory 打进 metadata 的归属标(create 半场,remote-env-e2b.ts);值恒 "1"。 */ export declare const SEMA_MANAGED_METADATA_KEY = "semaManaged"; /** provider 窄面(真实装配=E2B SDK `Sandbox.list()`/`Sandbox.kill()` 包装;测试注入 fake)。 */ export interface OrphanSandboxProvider { /** 列出**我方铸造**的沙盒(装配侧用 `query.metadata = { semaManaged: "1" }` 服务端过滤)。 */ listManaged(): Promise; kill(sandboxId: string): Promise; } export interface OrphanSandboxInfo { sandboxId: string; metadata: Record; /** SDK `SandboxInfo.startedAt`。 */ startedAt: Date; } export interface OrphanReclaimDeps { provider: OrphanSandboxProvider; /** RunStore 三形(TiDB/Pg/File)共同的窄读口。 */ runs: { getRun(taskId: string): Promise<{ status: string; } | undefined>; }; logger?: Logger; now?: () => number; graceMs?: number; } export interface OrphanReclaimSummary { scanned: number; reclaimed: number; skippedLive: number; skippedGrace: number; skippedUnknown: number; killFailed: number; } /** 一轮回收(boot 一次 + reaper interval 周期共用)。list 抛错穿透给调用方(reaper catch 族)。 */ export declare function reclaimOrphanE2bSandboxes(deps: OrphanReclaimDeps): Promise; /** 真实 provider(E2B SDK 包装)。SDK 静态面动态 import——回收腿只在 e2b 部署形挂载, * 非 e2b 形零加载(与 execution-env 的按需装配同姿势)。 */ export declare function createE2bOrphanSandboxProvider(cfg: { apiKey: string; }): OrphanSandboxProvider; //# sourceMappingURL=e2b-orphan-reclaim.d.ts.map