Documentation
¶
Overview ¶
Package generic provides generic retry combinators that work with any monadic type.
This package implements retry logic for monads that don't raise exceptions but signal failure in their type, such as Option, Either, and EitherT. The retry logic is parameterized over the monad operations, making it highly composable and reusable across different effect types.
Key Concepts ¶
The retry combinator takes:
- A retry policy that determines when and how long to wait between retries
- An action that produces a monadic value
- A check function that determines if the result should be retried
Usage with Different Monads ¶
The generic retry function can be used with any monad by providing the appropriate monad operations (Chain, Of, and Delay). This allows the same retry logic to work with IO, IOEither, ReaderIO, and other monadic types.
Example conceptual usage:
// For IOEither[E, A] result := Retrying( IOE.Chain[E, A], IOE.Chain[E, R.RetryStatus], IOE.Of[E, A], IOE.Of[E, R.RetryStatus], IOE.Delay[E, R.RetryStatus], policy, action, shouldRetry, )
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Retrying ¶
func Retrying[HKTTRAMPOLINE, HKTA, HKTSTATUS, A any]( monadChain func(func(A) HKTTRAMPOLINE) func(HKTA) HKTTRAMPOLINE, monadMapStatus func(func(R.RetryStatus) tailrec.Trampoline[R.RetryStatus, A]) func(HKTSTATUS) HKTTRAMPOLINE, monadOf func(tailrec.Trampoline[R.RetryStatus, A]) HKTTRAMPOLINE, monadOfStatus func(R.RetryStatus) HKTSTATUS, monadDelay func(time.Duration) func(HKTSTATUS) HKTSTATUS, tailRec func(func(R.RetryStatus) HKTTRAMPOLINE) func(R.RetryStatus) HKTA, policy R.RetryPolicy, action func(R.RetryStatus) HKTA, check func(A) bool, ) HKTA
Retrying implements a generic retry combinator that works with any monadic type. It repeatedly executes an action until either the check function returns false (indicating success) or the retry policy terminates (indicating failure).
This function is the core retry implementation that can be specialized for different monadic types (IO, IOEither, ReaderIO, etc.) by providing the appropriate monad operations. It uses tail recursion via trampolining to avoid stack overflow on deep retry chains.
How It Works ¶
The retry logic follows these steps:
- Execute the action with the current retry status
- Check the result using the check function
- If check returns false, return the result (success case)
- If check returns true, apply the retry policy to get the next delay
- If the policy returns None, stop retrying and return the last result
- If the policy returns Some(delay), wait for that duration and retry (step 1)
Type Parameters ¶
- HKTTRAMPOLINE: The higher-kinded type for the trampoline monad (e.g., IO[Trampoline[RetryStatus, A]])
- HKTA: The higher-kinded type for the action result (e.g., IO[A])
- HKTSTATUS: The higher-kinded type for the status monad (e.g., IO[RetryStatus])
- A: The result type of the action
Parameters ¶
Monad operations for the result type:
- monadChain: Chains computations in the result monad (flatMap/bind operation)
- monadMapStatus: Maps over the status monad to produce a trampoline
- monadOf: Lifts a trampoline value into the result monad
- monadOfStatus: Lifts a RetryStatus into the status monad
- monadDelay: Delays execution by a duration within the status monad
Tail recursion support:
- tailRec: Executes a tail-recursive function using trampolining to avoid stack overflow
Retry configuration:
- policy: The retry policy that determines delays and when to stop retrying
- action: The action to retry, which receives the current RetryStatus
- check: A predicate that returns true if the result should be retried, false otherwise
Returns ¶
The result of the action wrapped in the monad HKTA. This will be either:
- The first result where check returns false (success)
- The last result when the policy terminates (exhausted retries)
Example Usage Pattern ¶
For IOEither[E, A]:
result := Retrying( IOE.Chain[E, A], // Chain for IOEither[E, A] IOE.Chain[E, R.RetryStatus], // Chain for IOEither[E, RetryStatus] IOE.Of[E, A], // Lift trampoline to IOEither IOE.Of[E, R.RetryStatus], // Lift status to IOEither IOE.Delay[E, R.RetryStatus], // Delay in IOEither IOE.TailRec[R.RetryStatus, A], // Tail recursion for IOEither policy, // Retry policy action, // Action to retry E.IsLeft[A], // Retry on Left (error) )
Implementation Notes ¶
The function uses trampolining to implement tail recursion, which prevents stack overflow when retrying many times. The trampoline can be in one of two states:
- Land: Indicates completion with a final result
- Bounce: Indicates another iteration is needed with an updated status
The retry logic checks if the policy returned a delay (Some) or termination (None). If a delay is present, it bounces to the next iteration. If None, it lands with the current result.
Types ¶
This section is empty.