Durable Object が投げた未捕捉の例外、および Durable Objects インフラストラクチャが投げた例外(過負荷やネットワークエラーなど)は、クライアントの呼び出し元へ伝播します。これらの例外を捕捉すると、DurableObjectStub の再作成とリクエストの再送信を試せます。
.retryable プロパティが True の JavaScript Error は、Durable Object へのリクエストがべき等(何度適用しても応答が変わらない)であれば、再試行を推奨します。べき等でない場合は、アプリケーションに合わせて判断してください。再試行するときは、指数バックオフの適用を強く推奨します。
.overloaded プロパティが True の JavaScript Error は、再試行しないでください。Durable Object が過負荷のときに再試行すると、過負荷が悪化し、全体のエラー率が上がります。
Durable Objects が例外を投げる経路は、次の 2 つです。
- 例外を、Durable Object class を実装するユーザーコード内で投げる場合です。このとき、結果の例外には
.remoteプロパティがTrueで付きます。 - 例外を Durable Objects のインフラストラクチャが生成する場合です。インフラストラクチャ例外の例には、一時的な内部エラー、1 つの 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({});
}
}