first version
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package tinvest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
backofflib "github.com/cenkalti/backoff/v4"
|
||||
)
|
||||
|
||||
func withRetry(ctx context.Context, attempts int, interval time.Duration, fn func() error) error {
|
||||
if attempts <= 0 {
|
||||
attempts = 1
|
||||
}
|
||||
if interval < 0 {
|
||||
interval = 0
|
||||
}
|
||||
policy := backofflib.NewExponentialBackOff()
|
||||
policy.InitialInterval = interval
|
||||
policy.MaxInterval = interval * 8
|
||||
policy.Multiplier = 2
|
||||
policy.MaxElapsedTime = 0
|
||||
policy.Reset()
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < attempts; attempt++ {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fn(); err != nil {
|
||||
lastErr = err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
if attempt == attempts-1 || interval <= 0 {
|
||||
continue
|
||||
}
|
||||
timer := time.NewTimer(policy.NextBackOff())
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-ctx.Done():
|
||||
if !timer.Stop() {
|
||||
select {
|
||||
case <-timer.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
|
||||
func retryValue[T any](ctx context.Context, attempts int, interval time.Duration, fn func() (T, error)) (T, error) {
|
||||
var out T
|
||||
err := withRetry(ctx, attempts, interval, func() error {
|
||||
var err error
|
||||
out, err = fn()
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
var zero T
|
||||
return zero, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in New Issue
Block a user