package playback import ( "context" "time" ) type attemptFunc func(context.Context) error type retryDecider func(error) bool type waitFunc func(context.Context, time.Duration) error func waitForRetry(ctx context.Context, delay time.Duration) error { timer := time.NewTimer(delay) defer timer.Stop() select { case <-timer.C: return nil case <-ctx.Done(): return ctx.Err() } } func runWithRetry( ctx context.Context, policy RetryPolicy, attempt attemptFunc, shouldRetry retryDecider, wait waitFunc, ) error { failedAttempts := 0 for { err := attempt(ctx) if err == nil { return nil } if ctx.Err() != nil { return ctx.Err() } failedAttempts++ if !shouldRetry(err) || !policy.canRetry(failedAttempts) { return err } if err := wait(ctx, policy.retryDelay(failedAttempts)); err != nil { if ctx.Err() != nil { return ctx.Err() } return err } } }