14.1 问题:DO 会被驱逐
Durable Object 会因闲置(约 70–140 秒)、代码更新、alarm 超时(15 分钟)被赶走。长任务跑一半被踢,怎么办?
14.2 runFiber:可中断可恢复
runFiber 执行前在 SQLite 登记,执行中持有心跳,用 ctx.stash() 写检查点。被驱逐后,下次激活触发 onFiberRecovered。
class MyAgent extends Agent {
async doWork() {
await this.runFiber("my-task", async (ctx) => {
const step1 = await expensiveOperation();
ctx.stash({ step1 }); // 检查点
const step2 = await anotherOp(step1);
this.setState({ ...this.state, result: step2 });
});
}
async onFiberRecovered(ctx) {
if (ctx.name !== "my-task") return;
const snap = ctx.snapshot as { step1: unknown } | null;
if (snap) {
const step2 = await anotherOp(snap.step1); // 从检查点续
this.setState({ ...this.state, result: step2 });
}
}
}
14.3 长任务不丢进度
客户端断开?Agent 继续跑。重连?从 SQLite 读回进度接着发。AIChatAgent 的流式输出也有自动续传。
// 长效任务:启动-休眠-回调 模式
await this.runFiber("research", async (ctx) => {
const steps = ["search", "analyze", "synthesize"];
const completed: string[] = [];
for (const step of steps) {
await executeStep(step);
completed.push(step);
ctx.stash({ completed }); // 每步存盘
}
});
| 维度 | 普通 async | runFiber | 标叔的结论 |
|---|---|---|---|
| 被驱逐 | 进度丢 | 检查点续 | 长任务必用 |
| 客户端断开 | 可能中断 | 继续跑 | 体验好 |
| 复杂度 | 低 | 中 | 值 |
注意
stash()每次完全替换快照(不是 merge)。恢复逻辑必须写在onFiberRecovered,原 lambda 不可重放。
持久执行讲完。下一 Part 进工具与渠道:浏览器、沙箱、MCP、RAG、支付。