mcpField
D
durable-objects

durable-objects

github.com/cloudflare云与 DevOps3.2k112.9k 次安装今天更新
代码仓库

关于 durable-objects

面向使用 Cloudflare Durable Objects 构建边缘状态协调应用的编码技能,适合开发者实现和审查相关代码。它强调检索最新文档,并涵盖存储、并发、配置与测试规则。

主要功能

  1. 01状态协调实现指南
  2. 02RPC、闹钟与 WebSocket
  3. 03Wrangler 绑定和迁移
  4. 04SQLite 存储与并发规则
  5. 05Cloudflare Vitest 测试指南

适用场景

  1. 01实现聊天室或多人协作协调
  2. 02审查 Durable Object 代码
  3. 03配置绑定和迁移
  4. 04编写 Durable Object 测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cloudflare/skills --skill durable-objects

安装后在 Claude Code 中输入/durable-objects确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
rules.md
testing.md
workers.md

详细介绍

Durable Objects

使用 Durable Objects 在 Cloudflare 边缘构建有状态的协同应用。

检索资源

你对 Durable Objects API 和配置的了解可能已经过时。处理任何 Durable Objects 任务时,优先检索,而不是依赖预训练知识。

资源URL
文档https://developers.cloudflare.com/durable-objects/index.md
API 参考https://developers.cloudflare.com/durable-objects/api/index.md
最佳实践https://developers.cloudflare.com/durable-objects/best-practices/index.md
示例https://developers.cloudflare.com/durable-objects/examples/index.md
角色和权限https://developers.cloudflare.com/workers/authorization/durable-objects/index.md

实现功能时,请获取相关文档页面。

适用场景

  • 为有状态协同创建新的 Durable Object 类
  • 实现 RPC 方法、闹钟或 WebSocket 处理程序
  • 按最佳实践审查现有 DO 代码
  • 为 DO 绑定和迁移配置 wrangler.jsonc/toml
  • 使用 Cloudflare 的 Vitest 集成编写测试
  • 设计分片策略及父子关系

参考文档

  • ./references/rules.md - 核心规则、存储、并发、RPC、闹钟
  • 测试参考 - 当前 Vitest 文档、迁移选项和测试选择
  • ./references/workers.md - Workers 处理程序、类型、wrangler 配置、可观测性

搜索:blockConcurrencyWhile、idFromName、getByName、setAlarm、sql.exec

核心原则

适合使用 Durable Objects 的场景
需求示例
协同聊天室、多人游戏、协作文档
强一致性库存、预订系统、回合制游戏
按实体存储多租户 SaaS、按用户存储的数据
持久连接WebSocket、实时通知
按实体执行计划任务订阅续费、游戏超时
不要用于
  • 无状态请求处理(使用普通 Workers)
  • 对全局分布能力要求极高的场景
  • 大量扇出式的独立请求

快速参考

Wrangler 配置
// wrangler.jsonc
{
  "durable_objects": {
    "bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
Durable Object 基本模式
import { DurableObject } from "cloudflare:workers";

export interface Env {
  MY_DO: DurableObjectNamespace<MyDurableObject>;
}

export class MyDurableObject extends DurableObject<Env> {
  constructor(ctx: DurableObjectState, env: Env) {
    super(ctx, env);
    ctx.blockConcurrencyWhile(async () => {
      this.ctx.storage.sql.exec(`
        CREATE TABLE IF NOT EXISTS items (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          data TEXT NOT NULL
        )
      `);
    });
  }

  async addItem(data: string): Promise<number> {
    const result = this.ctx.storage.sql.exec<{ id: number }>(
      "INSERT INTO items (data) VALUES (?) RETURNING id",
      data
    );
    return result.one().id;
  }
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const stub = env.MY_DO.getByName("my-instance");
    const id = await stub.addItem("hello");
    return Response.json({ id });
  },
};

关键规则

  1. 围绕协同单元建模 - 每个聊天室、游戏或用户对应一个 DO,而不是使用一个全局 DO
  2. 使用 getByName() 实现确定性路由 - 相同输入 = 相同 DO 实例
  3. 使用 SQLite 存储 - 在迁移中配置 new_sqlite_classes
  4. 在构造函数中初始化 - 仅使用 blockConcurrencyWhile() 设置架构
  5. 使用 RPC 方法 - 不要使用 fetch() 处理程序(兼容性日期 >= 2024-04-03)
  6. 先持久化,再缓存 - 更新内存状态前,始终先写入存储
  7. 每个 DO 只能有一个闹钟 - setAlarm() 会替换现有闹钟

授权

Durable Objects 没有单独的角色或权限;访问权限遵循实现它们的 Worker。授予可观测性或 Data Studio 访问权限前,请查阅最新的 Durable Objects 授权指南,并将 Workers 角色的范围限定为目标 Worker 或 Workers 产品。

反模式(切勿采用)

  • 使用单个全局 DO 处理所有请求(会造成瓶颈)
  • 在每个请求上使用 blockConcurrencyWhile()(会严重降低吞吐量)
  • 仅在内存中存储关键状态(驱逐或崩溃时会丢失)
  • 在相关存储写入之间使用 await(会破坏原子性)
  • 在 fetch() 或外部 I/O 期间持有 blockConcurrencyWhile()

创建 Stub

// Deterministic - preferred for most cases
const stub = env.MY_DO.getByName("room-123");

// From existing ID string
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);

// New unique ID - store mapping externally
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);

存储操作

// SQL (synchronous, recommended)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();

// KV (async)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");

闹钟

// Schedule (replaces existing)
await this.ctx.storage.setAlarm(Date.now() + 60_000);

// Handler
async alarm(): Promise<void> {
  // Process scheduled work
  // Optionally reschedule: await this.ctx.storage.setAlarm(...)
}

// Cancel
await this.ctx.storage.deleteAlarm();

测试

配置测试套件或编写 Durable Object 测试前,请先阅读测试参考。该文档会指向当前的设置方式、API 和示例,并说明需要覆盖的行为。

评论

支持 Markdown