INTEGRITY Документация

Обработка ошибок

Любые необработанные исключения, выброшенные Durable Object либо выброшены инфраструктурой Durable Objects (например, из-за перегрузок или сетевых ошибок), будут переданы в место вызова на стороне клиента. Перехват этих исключений позволяет повторить попытку создания DurableObjectStub и отправки запросов.

Ошибки JavaScript со свойством .retryable со значением True рекомендуется повторять, если запросы к Durable Object идемпотентны, то есть их можно применять многократно без изменения результата. Если запросы не идемпотентны, решение о повторе следует принимать исходя из особенностей вашего приложения. При повторе запросов настоятельно рекомендуется использовать экспоненциальную задержку.

Ошибки JavaScript со свойством .overloaded со значением True повторять не следует. Если Durable Object перегружен, повтор запроса только усилит перегрузку и увеличит общую частоту ошибок.

Как выбрасываются исключения

Durable Objects могут выбрасывать исключения одним из двух способов:

См. Устранение неполадок чтобы ознакомиться с типами ошибок, которые возвращает 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({});
	}
}