跳到正文

快照与恢复

快照会冻结沙箱文件系统并返回一个ID。恢复会从该ID创建一个新沙箱。文件相同,状态相同,虚拟机不同。

机制很简单。出错的地方却没有。这三者都接近幂等性,即调用某事两次的结果与调用一次相同的性质。沙箱充满了你真的不想在不考虑的情况下重复调用的操作。

学习成果

你可以描述snapshot保护什么、restore创建了什么,并识别生产生命周期代码中出现的三种幂等性危害。

API

ts
const { snapshotId } = await sandbox.snapshot!();

const restored = await createCloudSandbox({ snapshotId });

那只是表面。所有有趣的事情都围绕着它发生。

快照保存了什么

快照捕捉文件系统状态。/workspace的内容(或者你沙箱根的地方)、任何已安装包的状态、Agent创建的任何文件。它们不会捕捉正在运行的进程、在运行中的网络连接或内存状态。一个运行已经过编译步骤一半的构建,在还原后不会从中断处继续。 文件系统快照;正在进行的工作则没有。

这对Agent的心理模型很重要。恢复后,Agent会保留之前所有的文件,但如果快照触发时正在运行测试,测试必须重新运行。

三大幂等性险

1. 快照正在进行中

用户(或生命周期工作流)在快照正在运行时触发快照。没有守卫,你会看到两个快照争夺同一个虚拟机,或者出现提供者错误,或者一个看起来有效但实际上不存在的部分快照。

ts
let inFlight: Promise<{ snapshotId: string }> | null = null;

snapshot: async () => {
  if (inFlight) return inFlight;
  inFlight = vm.snapshot();
  try {
    return await inFlight;
  } finally {
    inFlight = null;
  }
},

缓存承诺,第二调用天还回,工作完成后清除。

2. 沙箱已经在还原中运行

用户重新连接到已经活跃的会话,Harness会在会话上触发恢复。现在你有两个虚拟机。新车是在浪费钱。旧的那台还在为交通服务。

ts
async function attachOrRestore(sessionId: string, snapshotId: string) {
  const existing = await findActiveSandbox(sessionId);
  if (existing) return existing;
  return createCloudSandbox({ snapshotId });
}

创作前先看清楚。恢复路径应先检查是否有活跃沙箱。

3. 双音

stop由非活动计时器调用一次,用户调用一次。或者一次在休眠,一次在硬到期。第二个调用遇到的沙箱已经没了,根据供应商不同,要么大声故障,要么悄无声息地损坏状态。

ts
let stopped = false;

stop: async () => {
  if (stopped) return;
  stopped = true;
  await vm.close();
},

一个布尔值就足够了。关键是第二个stop没有做任何事,而不是直接攻击死机。

恢复解决不了的问题

快照是时间中的一个瞬间。从昨天的快照恢复,仍然会得到昨天的代码、昨天的依赖和昨天的环境。如果项目已经转移(新提交、新包、新环境变量),恢复后的沙箱就是化石。

生产生命周期通过在项目变更时失效快照,或在恢复后重运行安装钩子(模块4afterStart)来句柄这一点。这两者都不是自动的。两者都必须刻意接线。

**注意:当地沙箱可以伪造这个**

本地后端没有真正的快照机制,但你可以用git stash或 tarball 来绘制一个快照工作目录。它不等同于云快照(没有虚拟机状态,没有安装缓存),但它教会了接缝。如果你想玩玩形状,那是个不错的起点。

动手试试

这是一个概念课。自我检视:

  1. 不要回头,说出三个幂等性危险
  2. 用你自己的话写下snapshot保存和不保存的内容
  3. 用序列图勾勒attachOrRestore流程。活跃沙箱检查相对于快照查找在哪里进行?

如果你想本地玩形状,可以在本地沙箱添加一个snapshot,运行git stash push并返回仓库引用作为快照ID。语义上有问题(真实快照会冻结所有内容,不仅仅是追踪文件),但接缝是真实存在的。

提交

这节课里没有代码,除非你是在绘制本地快照。如果需要,建议把它提交到另一个分支,这样就不会和工作Harness纠缠。

完成标准

  • [ ] 你可以描述快照保留哪些内容,哪些不保留
  • [ ] 你可以说出三个幂等性危险和每个的防守模式
  • [ ] 你可以解释为什么恢复后的快照仍可能需要afterStart重新运行

非官方简体中文翻译 · 原课程来自 Vercel Academy