Skip to content

Instantly share code, notes, and snippets.

@dpeek
Created August 15, 2024 23:56
Show Gist options
  • Save dpeek/c0dab0a0c45eeee10fd3b89715274d29 to your computer and use it in GitHub Desktop.
Save dpeek/c0dab0a0c45eeee10fd3b89715274d29 to your computer and use it in GitHub Desktop.
Exponential backoff retry helper for DurableObjectStub
import { DurableObject } from 'cloudflare:workers';
const attempts = 3;
const baseBackoff = 100;
const maxBackoff = 20000;
function getBackoff(attempt: number) {
const backoff = baseBackoff * Math.pow(2, attempt) * Math.random();
return Math.round(Math.min(maxBackoff, backoff));
}
type DurableObjectCallback<T extends DurableObject, R> = (
stub: DurableObjectStub<T>,
) => Promise<R>;
export async function retry<T extends DurableObject, R>(
namespace: DurableObjectNamespace<T>,
name: string,
callback: DurableObjectCallback<T, R>,
): Promise<R> {
const id = namespace.idFromName(name);
let attempt = 0;
while (true) {
try {
const obj = namespace.get(id);
return await callback(obj);
} catch (error: any) {
// Failure was not a transient internal error, so don't retry.
if (!error.retryable) throw error;
// Reached max attempts, don't retry.
if (++attempt >= attempts) throw error;
const backoff = getBackoff(attempt);
console.log(`Caught "${error.message}" (attempt ${attempt}/${attempts})`);
await scheduler.wait(backoff);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment