mcpField
D
durable-objects

durable-objects

github.com/midudev云与 DevOps7.0k58 次安装1 周前更新
代码仓库

关于 durable-objects

durable-objects 是使用 Cloudflare Durable Objects 构建和审查有状态应用的技能,指引开发者查阅最新文档,并涵盖协调、存储、RPC、告警、配置与测试实践。

主要功能

  1. 01提供最新 Durable Objects 文档参考
  2. 02协调与一致性设计指导
  3. 03存储、RPC 和告警模式
  4. 04Wrangler 绑定与迁移配置
  5. 05测试和代码审查指导

适用场景

  1. 01构建聊天或多人游戏协调功能
  2. 02设计实体级持久状态
  3. 03配置 Durable Objects 绑定与迁移
  4. 04审查 Durable Objects 代码和测试

安装

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

$npx skills add https://github.com/midudev/autoskills --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