generic

package
v2.1.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

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:

  1. Execute the action with the current retry status
  2. Check the result using the check function
  3. If check returns false, return the result (success case)
  4. If check returns true, apply the retry policy to get the next delay
  5. If the policy returns None, stop retrying and return the last result
  6. 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL