~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
77 lines · 1.5 KB Raw History
package runtime

import (
	"sync"
	"time"

	"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/opt"
	mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

const (
	DefaultBackoffBase = 500 * time.Millisecond

	DefaultBackoffMax = 5 * time.Minute

	ExportRetryFirst = 50 * time.Millisecond
)

type backoff struct {
	base time.Duration

	max time.Duration

	mu sync.Mutex

	failures map[mcreconcile.Request]int
}

func newBackoff(base, max time.Duration) *backoff {
	base = opt.Positive(base, DefaultBackoffBase)
	if max < base {
		max = base
	}
	return &backoff{base: base, max: max, failures: map[mcreconcile.Request]int{}}
}

func (b *backoff) delay(n int) time.Duration {
	d := b.base
	for i := 0; i < n && d < b.max; i++ {
		d *= 2
	}
	if d > b.max {
		d = b.max
	}
	return d
}

func (b *backoff) When(item mcreconcile.Request) time.Duration {
	b.mu.Lock()
	defer b.mu.Unlock()
	n := b.failures[item]
	b.failures[item] = n + 1
	return b.delay(n)
}

func (b *backoff) Forget(item mcreconcile.Request) {
	b.mu.Lock()
	defer b.mu.Unlock()
	delete(b.failures, item)
}

func (b *backoff) NumRequeues(item mcreconcile.Request) int {
	b.mu.Lock()
	defer b.mu.Unlock()
	return b.failures[item]
}

func (b *backoff) peek(item mcreconcile.Request) (int, time.Duration) {
	b.mu.Lock()
	defer b.mu.Unlock()
	n := b.failures[item]
	return n + 1, b.delay(n)
}

func BackoffDelay(base, max time.Duration, failures int) time.Duration {
	return newBackoff(base, max).delay(failures)
}