Execution Cancellation
Failsafe-go supports execution cancellation, which can be triggered in a few ways. It can be triggered by a Timeout:
// Cancel Connect call after 1 second
failsafe.Get(Connect, timeout.With(time.Second))
By a Context:
ctx, _ := context.WithTimeout(context.Background(), time.Second)
// Connect will be canceled by the ctx after 1 second
failsafe.NewExecutor[any](retryPolicy).WithContext(ctx).Get(Connect)
Or by an async ExecutionResult:
result := failsafe.RunAsync(Connect, retryPolicy)
result.Cancel()
Outstanding hedge executions are also canceled once a successful result is received.
Propagating Cancellations
For executions that may be canceled by a policy such as a timeout or hedge policy, a child context is created and made available via Context(), which should be used to propagate these cancellations to downstream code:
failsafe.GetWithExecution(func(exec failsafe.Execution[*http.Response]) (*http.Response, error) {
request, err := http.NewRequestWithContext(exec.Context(), http.MethodGet, url, nil)
return client.Do(request)
}, timeout)
Cooperative Cancellation
Executions can cooperate with a cancellation by periodically checking IsCanceled():
failsafe.RunWithExecution(func(exec failsafe.Execution[any]) error {
for {
if !exec.IsCanceled() {
if err := DoWork(); err != nil {
return err
}
}
}
return nil
}, timeout)
Executions can also use the Canceled() channel to detect when an execution is canceled:
failsafe.RunWithExecution(func(exec failsafe.Execution[any]) error {
for {
select {
case <-exec.Canceled():
return nil
case task := <-GetTask():
Process(task)
}
}
return nil
}, timeout)
Timeout vs Context Cancellation
While a cancellation from a Timeout can still be retried by an outer RetryPolicy, a cancellation from a Context or ExecutionResult cannot be.