Add PostgreSQL and Redis integration for users and sessions Implement password and WebAuthn passkey login flows Add Docker stack, super-admin seeding, and protected routes
40 lines
876 B
TypeScript
40 lines
876 B
TypeScript
export interface RetryOptions {
|
|
retries?: number
|
|
delayMs?: number
|
|
factor?: number
|
|
label?: string
|
|
}
|
|
|
|
function sleep(delayMs: number) {
|
|
return new Promise((resolve) => setTimeout(resolve, delayMs))
|
|
}
|
|
|
|
export async function withRetry<T>(
|
|
operation: () => Promise<T>,
|
|
options: RetryOptions = {}
|
|
) {
|
|
const retries = options.retries ?? 10
|
|
const delayMs = options.delayMs ?? 1_000
|
|
const factor = options.factor ?? 1.5
|
|
const label = options.label ?? 'operation'
|
|
|
|
let attempt = 0
|
|
let currentDelay = delayMs
|
|
|
|
while (true) {
|
|
try {
|
|
return await operation()
|
|
} catch (error) {
|
|
attempt += 1
|
|
|
|
if (attempt > retries) {
|
|
throw error
|
|
}
|
|
|
|
console.warn(`${label} failed on attempt ${attempt}. Retrying in ${currentDelay}ms.`)
|
|
await sleep(currentDelay)
|
|
currentDelay = Math.round(currentDelay * factor)
|
|
}
|
|
}
|
|
}
|