Files
sendico/api/edge/callbacks/internal/retry/service.go
2026-02-28 10:10:26 +01:00

60 lines
1.0 KiB
Go

package retry
import (
"math"
"math/rand"
"sync"
"time"
)
type service struct {
mu sync.Mutex
rnd *rand.Rand
}
// New creates retry policy service.
func New() Policy {
return &service{rnd: rand.New(rand.NewSource(time.Now().UnixNano()))}
}
func (s *service) NextAttempt(attempt int, now time.Time, minDelay, maxDelay time.Duration, jitterRatio float64) time.Time {
if attempt < 1 {
attempt = 1
}
if minDelay <= 0 {
minDelay = time.Second
}
if maxDelay < minDelay {
maxDelay = minDelay
}
base := float64(minDelay)
delay := time.Duration(base * math.Pow(2, float64(attempt-1)))
if delay > maxDelay {
delay = maxDelay
}
if jitterRatio > 0 {
if jitterRatio > 1 {
jitterRatio = 1
}
maxJitter := int64(float64(delay) * jitterRatio)
if maxJitter > 0 {
s.mu.Lock()
jitter := s.rnd.Int63n((maxJitter * 2) + 1)
s.mu.Unlock()
delta := jitter - maxJitter
delay += time.Duration(delta)
}
}
if delay < minDelay {
delay = minDelay
}
if delay > maxDelay {
delay = maxDelay
}
return now.UTC().Add(delay)
}