Skip to content

retry_handler

retry_handler

Retry handling with exponential backoff.

Provides robust retry logic for transient failures.

RetryableError

Bases: Exception

Base class for errors that should be retried.

RateLimitError

Bases: RetryableError

Rate limit exceeded error.

NetworkError

Bases: RetryableError

Network-related error.

RetryHandler

RetryHandler(max_attempts: int = 3, initial_delay: float = 1.0, max_delay: float = 60.0, exponential_base: int = 2, retryable_exceptions: tuple[type[Exception], ...] | None = None)

Request-level retry with exponential backoff (for transient errors).

Scope: Single LLM API call or operation Use when: Transient errors (rate limits, network timeouts, API hiccups) NOT for: Row-level quality issues (use Pipeline.auto_retry_failed for that)

Retry Strategy: - Exponential backoff (1s, 2s, 4s, 8s, ...) - Configurable max attempts (default: 3) - Only retries specific exception types

Example

handler = RetryHandler(max_attempts=3, initial_delay=1.0) result = handler.execute(lambda: call_llm_api())

See Also: - ErrorHandler: Orchestrates retry decisions based on policy - Pipeline._auto_retry_failed_rows(): Row-level quality retry - docs/architecture/decisions/ADR-006-retry-levels.md

Initialize retry handler.

Parameters:

Name Type Description Default
max_attempts int

Maximum retry attempts

3
initial_delay float

Initial delay in seconds

1.0
max_delay float

Maximum delay in seconds

60.0
exponential_base int

Base for exponential backoff

2
retryable_exceptions tuple[type[Exception], ...] | None

Exception types to retry

None
Source code in ondine/utils/retry_handler.py
def __init__(
    self,
    max_attempts: int = 3,
    initial_delay: float = 1.0,
    max_delay: float = 60.0,
    exponential_base: int = 2,
    retryable_exceptions: tuple[type[Exception], ...] | None = None,
):
    """
    Initialize retry handler.

    Args:
        max_attempts: Maximum retry attempts
        initial_delay: Initial delay in seconds
        max_delay: Maximum delay in seconds
        exponential_base: Base for exponential backoff
        retryable_exceptions: Exception types to retry
    """
    self.max_attempts = max_attempts
    self.initial_delay = initial_delay
    self.max_delay = max_delay
    self.exponential_base = exponential_base

    if retryable_exceptions is None:
        self.retryable_exceptions = (
            RetryableError,
            RateLimitError,
            NetworkError,
        )
    else:
        self.retryable_exceptions = retryable_exceptions

execute

execute(func: Callable[[], T]) -> T

Execute function with retry logic.

Parameters:

Name Type Description Default
func Callable[[], T]

Function to execute

required

Returns:

Type Description
T

Result from function

Raises:

Type Description
Exception

If all retries exhausted

Source code in ondine/utils/retry_handler.py
def execute(self, func: Callable[[], T]) -> T:
    """
    Execute function with retry logic.

    Args:
        func: Function to execute

    Returns:
        Result from function

    Raises:
        Exception: If all retries exhausted
    """
    retryer = Retrying(
        stop=stop_after_attempt(self.max_attempts),
        wait=wait_exponential(
            multiplier=self.initial_delay,
            max=self.max_delay,
            exp_base=self.exponential_base,
        ),
        retry=retry_if_exception_type(self.retryable_exceptions),
        reraise=True,
    )

    return retryer(func)

calculate_delay

calculate_delay(attempt: int) -> float

Calculate delay for given attempt number.

Parameters:

Name Type Description Default
attempt int

Attempt number (1-based)

required

Returns:

Type Description
float

Delay in seconds

Source code in ondine/utils/retry_handler.py
def calculate_delay(self, attempt: int) -> float:
    """
    Calculate delay for given attempt number.

    Args:
        attempt: Attempt number (1-based)

    Returns:
        Delay in seconds
    """
    delay = self.initial_delay * (self.exponential_base ** (attempt - 1))
    return min(delay, self.max_delay)