Durable Object 或 Durable Objects 基础设施(如过载或网络错误)抛出的任何未捕获异常都会传播到客户端调用点。捕获这些异常允许您重试创建 DurableObjectStub 并发送请求。
属性 .retryable 设置为 True 的 JavaScript 错误建议在 Durable Object 请求是幂等的,或可以多次应用而不改变响应的情况下重试。如果请求不是幂等的,您需要决定最适合应用的方案。强烈建议在重试请求时应用指数退避。
属性 .overloaded 设置为 True 的 JavaScript 错误不应重试。如果 Durable Object 过载,重试会加剧过载并增加整体错误率。
Durable Objects 可以通过两种方式抛出异常:
- 实现 Durable Object 类 的用户代码内可以抛出异常。此情况下,产生的异常将设置
.remote属性为True。 - Durable Objects 基础设施可以生成异常。基础设施异常的一些来源包括:临时内部错误、向单个 Durable Object 发送过多请求,以及由于单个 Durable Object 内缓慢或过度的 I/O(外部 API 调用或存储操作)导致排队请求过多。某些基础设施异常也可能设置
.remote属性为True——例如,当 Durable Object 超过其内存或 CPU 限制时。
请参阅故障排查了解 Durable Object 和/或 Durable Objects 基础设施返回的错误类型以及如何防止它们。
此示例演示使用推荐的指数退避算法重试请求。
import { DurableObject } from "cloudflare:workers";
export interface Env {
ErrorThrowingObject: DurableObjectNamespace;
}
export default {
async fetch(request, env, ctx) {
let userId = new URL(request.url).searchParams.get("userId") || "";
// Retry behavior can be adjusted to fit your application.
let maxAttempts = 3;
let baseBackoffMs = 100;
let maxBackoffMs = 20000;
let attempt = 0;
while (true) {
// Try sending the request
try {
// Create a Durable Object stub for each attempt, because certain types of
// errors will break the Durable Object stub.
const doStub = env.ErrorThrowingObject.getByName(userId);
const resp = await doStub.fetch("http://your-do/");
return Response.json(resp);
} catch (e: any) {
if (!e.retryable) {
// Failure was not a transient internal error, so don't retry.
break;
}
}
let backoffMs = Math.min(
maxBackoffMs,
baseBackoffMs * Math.random() * Math.pow(2, attempt),
);
attempt += 1;
if (attempt >= maxAttempts) {
// Reached max attempts, so don't retry.
break;
}
await scheduler.wait(backoffMs);
}
return new Response("server error", { status: 500 });
},
} satisfies ExportedHandler<Env>;
export class ErrorThrowingObject extends DurableObject {
constructor(state: DurableObjectState, env: Env) {
super(state, env);
// Any exceptions that are raised in your constructor will also set the
// .remote property to True
throw new Error("no good");
}
async fetch(req: Request) {
// Generate an uncaught exception
// A .remote property will be added to the exception propagated to the caller
// and will be set to True
throw new Error("example error");
// We never reach this
return Response.json({});
}
}