durable-objects by cloudflare/skills
npx skills add https://github.com/cloudflare/skills --skill durable-objects在 Cloudflare 边缘网络上构建有状态、可协调的应用程序。
您对 Durable Objects API 和配置的了解可能已过时。对于任何 Durable Objects 任务,优先使用检索而非预训练。
实现功能时,请获取相关的文档页面。
@cloudflare/vitest-pool-workers 编写测试广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
./references/rules.md - 核心规则、存储、并发、RPC、警报./references/testing.md - Vitest 设置、单元/集成测试、警报测试./references/workers.md - Workers 处理程序、类型、wrangler 配置、可观测性搜索:blockConcurrencyWhile、idFromName、getByName、setAlarm、sql.exec
| 需求 | 示例 |
|---|---|
| 协调 | 聊天室、多人游戏、协作文档 |
| 强一致性 | 库存系统、预订系统、回合制游戏 |
| 按实体存储 | 多租户 SaaS、用户数据 |
| 持久连接 | WebSockets、实时通知 |
| 按实体调度工作 | 订阅续订、游戏超时 |
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
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 });
},
};
getByName() 进行确定性路由 - 相同输入 = 相同 DO 实例new_sqlite_classesblockConcurrencyWhile() 用于模式设置setAlarm() 会替换任何现有警报blockConcurrencyWhile()(扼杀吞吐量)await(破坏原子性)fetch() 或外部 I/O 期间持有 blockConcurrencyWhile()// 确定性 - 大多数情况下的首选
const stub = env.MY_DO.getByName("room-123");
// 从现有 ID 字符串
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// 新的唯一 ID - 在外部存储映射关系
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);
// SQL(同步,推荐)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV(异步)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");
// 调度(替换现有警报)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// 处理程序
async alarm(): Promise<void> {
// 处理调度的工作
// 可选择重新调度:await this.ctx.storage.setAlarm(...)
}
// 取消
await this.ctx.storage.deleteAlarm();
import { env } from "cloudflare:test";
import { describe, it, expect } from "vitest";
describe("MyDO", () => {
it("should work", async () => {
const stub = env.MY_DO.getByName("test");
const result = await stub.addItem("test");
expect(result).toBe(1);
});
});
每周安装量
1.9K
代码库
GitHub Stars
566
首次出现
2026年1月19日
安全审计
安装于
opencode1.6K
codex1.6K
gemini-cli1.5K
github-copilot1.4K
amp1.3K
claude-code1.3K
Build stateful, coordinated applications on Cloudflare's edge using Durable Objects.
Your knowledge of Durable Objects APIs and configuration may be outdated. Prefer retrieval over pre-training for any Durable Objects task.
Fetch the relevant doc page when implementing features.
@cloudflare/vitest-pool-workers./references/rules.md - Core rules, storage, concurrency, RPC, alarms./references/testing.md - Vitest setup, unit/integration tests, alarm testing./references/workers.md - Workers handlers, types, wrangler config, observabilitySearch: blockConcurrencyWhile, idFromName, getByName, setAlarm, sql.exec
| Need | Example |
|---|---|
| Coordination | Chat rooms, multiplayer games, collaborative docs |
| Strong consistency | Inventory, booking systems, turn-based games |
| Per-entity storage | Multi-tenant SaaS, per-user data |
| Persistent connections | WebSockets, real-time notifications |
| Scheduled work per entity | Subscription renewals, game timeouts |
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
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 });
},
};
getByName() for deterministic routing - Same input = same DO instancenew_sqlite_classes in migrationsblockConcurrencyWhile() for schema setup onlysetAlarm() replaces any existing alarmblockConcurrencyWhile() on every request (kills throughput)await between related storage writes (breaks atomicity)blockConcurrencyWhile() across fetch() or external I/O// 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();
import { env } from "cloudflare:test";
import { describe, it, expect } from "vitest";
describe("MyDO", () => {
it("should work", async () => {
const stub = env.MY_DO.getByName("test");
const result = await stub.addItem("test");
expect(result).toBe(1);
});
});
Weekly Installs
1.9K
Repository
GitHub Stars
566
First Seen
Jan 19, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode1.6K
codex1.6K
gemini-cli1.5K
github-copilot1.4K
amp1.3K
claude-code1.3K
99,500 周安装