'use strict';
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function backoffDelay(attempt, baseMs, maxDelayMs) {
const exponential = baseMs * 2 ** attempt;
export class TimeoutError extends Error {
constructor(public readonly ms: number) {
super(`Request timed out after ${ms}ms`);
this.name = "TimeoutError";
}
}
class SyncContactJob < ApplicationJob
queue_as :external
BACKOFF = ->(executions) do
(2**executions) + rand(0.0..1.0) # exponential + jitter, in seconds
end
package httpretry
import (
"math/rand"
"time"
)
use std::time::Duration;
use rand::Rng;
#[derive(Clone, Debug)]
pub struct BackoffPolicy {
pub base_delay: Duration,
import random
from dataclasses import dataclass
from typing import Iterator
@dataclass(frozen=True)
const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
export function isRetryable(error: unknown, response?: Response): boolean {
if (response) {
return RETRYABLE_STATUS.has(response.status);
}
import java.time.Duration;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Predicate;
public final class RetryPolicy {
private final int maxAttempts;
class CircuitBreaker
class CircuitOpenError < StandardError; end
def initialize(name, redis: Redis.current, failure_threshold: 5, failure_window: 60, cooldown: 30)
@key = "circuit:#{name}"
@redis = redis
const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
export function fullJitter(attempt, baseDelay = 300, maxDelay = 10_000) {
const ceiling = Math.min(maxDelay, baseDelay * 2 ** attempt);
return Math.random() * ceiling;
}