owpengram-server/internal/rpc/idle_backoff.go

65 lines
1.1 KiB
Go

package rpc
import (
"context"
"time"
)
const defaultIdleDispatchMaxInterval = 5 * time.Second
type idleBackoff struct {
base time.Duration
max time.Duration
next time.Duration
}
func newIdleBackoff(base, max time.Duration) idleBackoff {
if base <= 0 {
base = time.Second
}
if max < base {
max = base
}
return idleBackoff{
base: base,
max: max,
next: base,
}
}
func (b *idleBackoff) ActiveDelay() time.Duration {
b.next = b.base
return b.base
}
func (b *idleBackoff) IdleDelay() time.Duration {
delay := b.next
if b.next < b.max {
b.next *= 2
if b.next > b.max {
b.next = b.max
}
}
return delay
}
func runIdleBackoffLoop(ctx context.Context, interval, maxIdleInterval time.Duration, dispatch func(context.Context) bool) {
if dispatch == nil {
return
}
backoff := newIdleBackoff(interval, maxIdleInterval)
timer := time.NewTimer(0)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return
case <-timer.C:
}
if dispatch(ctx) {
timer.Reset(backoff.ActiveDelay())
continue
}
timer.Reset(backoff.IdleDelay())
}
}