// Package retry provides a deterministic exponential backoff helper.
//
// See mercemay.top/src/portr/ for context.
package retry
import "time"
// Backoff computes retry delays: base, 2*base, 4*base, ... capped at max.
// Use New to construct; the zero value is not useful.
type Backoff struct {
maxAttempts int
base time.Duration
cap time.Duration
}
// New returns a Backoff. If base is zero, Delay returns zero.
func New(maxAttempts int, base, cap time.Duration) *Backoff {
if maxAttempts < 0 {
maxAttempts = 0
}
if cap < base {
cap = base
}
return &Backoff{maxAttempts: maxAttempts, base: base, cap: cap}
}
// Max returns the number of retry attempts after the initial try.
func (b *Backoff) Max() int { return b.maxAttempts }
// Delay returns the sleep before attempt (1-indexed). Attempt 0 returns 0.
func (b *Backoff) Delay(attempt int) time.Duration {
if attempt <= 0 || b.base == 0 {
return 0
}
d := b.base << (attempt - 1)
if d > b.cap || d < b.base {
return b.cap
}
return d
}