Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

エラー処理

最終更新 Markdown で表示Agent セットアップ

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({});
	}
}

役に立ちましたか?