pkg.go.dev

Package failsafe provides fault tolerance and resilience patterns.

Failsafe-go adds fault tolerance to function execution. Functions can be wrapped with one or more resilience policies, for example:

result, err := failsafe.With(retryPolicy).Get(fn)

When multiple policies are provided, are composed around the fn and will handle its results in reverse order. For example, consider:

failsafe.With(fallback, retryPolicy, circuitBreaker).Get(fn)

This creates the following composition when executing the fn and handling its result:

Fallback(RetryPolicy(CircuitBreaker(fn)))

This section is empty.

ErrExecutionCanceled indicates that an execution was canceled by ExecutionResult.Cancel.

This section is empty.

DelayFunc returns a duration to delay for given the ExecutionAttempt.

type DelayablePolicyBuilder[S any, R any] interface {

	WithDelay(delay time.Duration) S

	WithDelayFunc(delayFunc DelayFunc[R]) S
}

DelayablePolicyBuilder builds policies that can be delayed between executions.

type Execution[R any] interface {
	ExecutionAttempt[R]

	IsCanceled() bool


	Canceled() <-chan struct{}
}

Execution contains information about an execution.

ExecutionAttempt contains information for an execution attempt.

type ExecutionDoneEvent[R any] struct {
	ExecutionInfo

	Result R

	Error error
}

ExecutionDoneEvent indicates an execution is done.

type ExecutionEvent[R any] struct {
	ExecutionAttempt[R]
}

ExecutionEvent indicates an execution was attempted.

ExecutionInfo contains execution info.

type ExecutionResult[R any] interface {

	Done() <-chan any

	IsDone() bool

	Get() (R, error)

	Result() R

	Error() error


	Cancel()
}

ExecutionResult provides the result of an asynchronous execution.

ExecutionScheduledEvent indicates an execution was scheduled.

type Executor[R any] interface {

	Compose(innerPolicy Policy[R]) Executor[R]


	ComposeAny(innerPolicy ResultAgnosticPolicy[any]) Executor[R]

	Context() context.Context


	WithContext(ctx context.Context) Executor[R]

	OnDone(listener func(ExecutionDoneEvent[R])) Executor[R]


	OnSuccess(listener func(ExecutionDoneEvent[R])) Executor[R]


	OnFailure(listener func(ExecutionDoneEvent[R])) Executor[R]


	Run(fn func() error) error


	RunWithExecution(fn func(exec Execution[R]) error) error


	Get(fn func() (R, error)) (R, error)


	GetWithExecution(fn func(exec Execution[R]) (R, error)) (R, error)


	RunAsync(fn func() error) ExecutionResult[R]


	RunAsyncWithExecution(fn func(exec Execution[R]) error) ExecutionResult[R]


	GetAsync(fn func() (R, error)) ExecutionResult[R]


	GetAsyncWithExecution(fn func(exec Execution[R]) (R, error)) ExecutionResult[R]
}

Executor handles failures according to configured policies. See With for details on creating an Executor.

R is the result type. This type is concurrency safe.

func With[R any](policies ...Policy[R]) Executor[R]

With creates and returns a new Executor for result type R that will handle failures according to the given policies. The policies are composed around a func and will handle its results in reverse order. For example, consider:

failsafe.With(fallback, retryPolicy, circuitBreaker).Get(fn)

This creates the following composition when executing a func and handling its result:

Fallback(RetryPolicy(CircuitBreaker(func)))

WithAny creates and returns a new Executor that can be used to compose other policies with the result type R, for the final composed execution. The executor will handle failures according to the given policies.

type FailurePolicyBuilder[S any, R any] interface {


	HandleErrors(errs ...error) S


	HandleErrorTypes(errs ...any) S


	HandleResult(result R) S

	HandleIf(predicate func(R, error) bool) S

	OnSuccess(listener func(ExecutionEvent[R])) S


	OnFailure(listener func(ExecutionEvent[R])) S
}

FailurePolicyBuilder builds a Policy that allows configurable conditions to determine whether an execution is a failure.

  • By default, any error is considered a failure and will be handled by the policy. You can override this by specifying your own handle conditions. The default error handling condition will only be overridden by another condition that handles errors such as Handle or HandleIf. Specifying a condition that only handles results, such as HandleResult will not replace the default error handling condition.
  • If multiple handle conditions are specified, any condition that matches an execution result or error will trigger policy handling.
type Policy[R any] interface {


	ToExecutor(typeToken R) any
}

Policy handles execution failures.

type ResultAgnosticPolicy[R any] interface {
	Policy[R]


	ResultAgnostic()
}

ResultAgnosticPolicy is a marker interface for policies that do not modify or return alternate results. Such policies can be composed with any as the result type along with policies that have more specific result types.

Read the original on pkg.go.dev ↗