Kind: Service
Source: atloria-monorepo/apps/screenshot-worker/src/app/screenshot/services/retry-handler.service.ts
RetryHandlerService centralizes retry behavior for screenshot-worker operations that may fail transiently, such as network requests or temporary browser failures. It classifies errors as retryable, calculates exponential backoff delays, and reruns asynchronous work until it succeeds or the retry limit is reached.
Methods
| Method | Signature | Returns | Description |
|---|---|---|---|
isRetryableError | `isRetryableError(error: Error | string | null |
calculateBackoffDelay | calculateBackoffDelay(attempt: number, config: RetryConfig) | number | Calculates the backoff delay for a given attempt Formula: min(initialDelayMs * (backoffMultiplier ^ (attempt - 1)), maxDelayMs) |
retryWithBackoff | retryWithBackoff(fn: () => Promise<T>, config: RetryConfig) | Promise<T> | Executes a function with automatic retry and exponential backoff |
Where it refuses work
RetryHandlerServicestops the work with an early return whenregex.test(errorMessage) || regex.test(errorName), in 2 places.RetryHandlerServicestops the work with an early return when!error.RetryHandlerServicestops the work with an early return whenNON_RETRYABLE_ERROR_NAMES.includes(errorName).RetryHandlerServicestops the work with an early return whenattempt <= 0.
When something fails
RetryHandlerServicehandles failure in 1 place: it lets it reach the caller in all 1.
Diagram
mermaidsequenceDiagram participant Caller participant RetryHandlerService participant Operation Caller->>RetryHandlerService: retryWithBackoff(operation) RetryHandlerService->>Operation: execute() alt Operation succeeds Operation-->>RetryHandlerService: result RetryHandlerService-->>Caller: result else Operation fails Operation-->>RetryHandlerService: error RetryHandlerService->>RetryHandlerService: isRetryableError(error) alt Retryable and attempts remain RetryHandlerService->>RetryHandlerService: calculateBackoffDelay(attempt) RetryHandlerService->>RetryHandlerService: wait(delay) RetryHandlerService->>Operation: execute again else Not retryable or limit reached RetryHandlerService-->>Caller: throw error end end
Usage
tsimport { Injectable } from '@nestjs/common';
import { RetryHandlerService } from './retry-handler.service';
@Injectable()
export class ScreenshotGenerationService {
constructor(
private readonly retryHandlerService: RetryHandlerService,
) {}
async captureScreenshot(url: string): Promise<Buffer> {
return this.retryHandlerService.retryWithBackoff(async () => {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to load page: ${response.status}`);
}
return Buffer.from(await response.arrayBuffer());
});
}
}
AI Coding Instructions
- Use
retryWithBackofffor asynchronous operations that can safely be repeated without creating duplicate side effects. - Keep retry classification in
isRetryableError; add new transient error types there rather than duplicating retry checks in callers. - Preserve the backoff calculation in
calculateBackoffDelayso retry timing remains consistent across screenshot-worker services. - Do not retry validation errors, malformed input, authorization failures, or other deterministic failures.
- Ensure callers log enough context about the failed operation, but avoid logging sensitive URLs, credentials, or request payloads.
Referenced By
ScreenshotModule(MODULE_PROVIDES)BatchScreenshotService(DEPENDS_ON)
Was this page helpful?