Problem
You are building a small library component called a Retryer that wraps an operation (typically a network call) and retries it on failure.
Requirements
-
Default behavior
-
Provide a “default retryer” implementation that retries an operation when it fails.
-
The default should support common retry features:
-
Maximum attempts (or max retries)
-
Delay/backoff strategy (e.g., fixed, exponential)
-
Optional jitter
-
Stop conditions (e.g., do not retry on certain exception types / status codes)
-
Ability to honor a caller-provided cancellation/deadline (e.g., timeout)
-
Extensibility
-
The design must be
extensible
so that callers can plug in custom behavior without modifying the retryer’s core logic. Examples:
-
Custom backoff policy
-
Custom “should retry?” policy
-
Hooks/observers for logging/metrics
-
Handling server-provided retry hints (e.g., a
Retry-After
value)
-
Usability
-
The API should be easy to use for common cases, while still allowing advanced customization.
What to deliver
-
Propose the public API (interfaces/classes) for the Retryer.
-
Explain how the default retryer works.
-
Explain how customizations are added (e.g., strategies, composition, configuration objects).
-
Call out key edge cases and pitfalls (e.g., thundering herd, non-idempotent operations, deadlines).