<commit_before>package network

import (
	"golang.org/x/time/rate"
	"math"
	"math/rand"
	"time"
)

type Throttler struct {
	limiter   *rate.Limiter
	onBackOff func(int)
}

func NewThrottler(throttleLimit int, onBackOffFn func(int)) Throttler {
	return Throttler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: onBackOffFn,
	}
}

func NewStaticBackoffThrottler(throttleLimit int, backOffDuration time.Duration) Throttler {
	return Throttler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: staticBackoffFn(backOffDuration),
	}
}

func staticBackoffFn(backOffDuration time.Duration) func(attempt int) {
	return func(_ int) {
		time.Sleep(backOffDuration)
	}
}

func NewIncrementalBackoffThrottler(throttleLimit int, backOffDuration time.Duration, incrementDuration time.Duration) Throttler {
	return Throttler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: incrementalBackoffFn(backOffDuration, incrementDuration),
	}
}

func incrementalBackoffFn(backOffDuration time.Duration, incrementDuration time.Duration) func(attempt int) {
	return func(attempt int) {
		sleepMillis := float64(backOffDuration.Milliseconds()) + math.Pow(float64(incrementDuration), float64(attempt))
		time.Sleep(time.Duration(sleepMillis) * time.Millisecond)
	}
}

func NewRandomisedBackoffThrottler(throttleLimit int, minDuration, maxDuration time.Duration) Throttler {
	return Throttler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: randomisedBackoffFn(maxDuration, minDuration),
	}
}

func randomisedBackoffFn(maxDuration time.Duration, minDuration time.Duration) func(attempt int) {
	return func(attempt int) {
		randMillis := (rand.Int63() * (maxDuration.Milliseconds() - minDuration.Milliseconds())) + minDuration.Milliseconds()
		time.Sleep(time.Duration(randMillis) * time.Millisecond)
	}
}

func (t *Throttler) Acquire() {
	attempt := 0
	for {
		if t.limiter.Allow() {
			break
		}

		attempt += 1
		t.onBackOff(attempt)
	}
}<commit_msg>AV-502 Limit number of outbound connections a node tries to open at once<commit_after>package network

import (
	"golang.org/x/time/rate"
	"math"
	"math/rand"
	"time"
)

type Throttler interface {
	Acquire()
}

type BlockingThrottler struct {
	limiter   *rate.Limiter
	onBackOff func(int)
}

func (t BlockingThrottler) Acquire() {
	attempt := 0
	for {
		if t.limiter.Allow() {
			break
		}

		attempt += 1
		t.onBackOff(attempt)
	}
}

func NewThrottler(throttleLimit int, onBackOffFn func(int)) Throttler {
	return BlockingThrottler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: onBackOffFn,
	}
}

func NewStaticBackoffThrottler(throttleLimit int, backOffDuration time.Duration) Throttler {
	return BlockingThrottler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: staticBackoffFn(backOffDuration),
	}
}

func staticBackoffFn(backOffDuration time.Duration) func(attempt int) {
	return func(_ int) {
		time.Sleep(backOffDuration)
	}
}

func NewIncrementalBackoffThrottler(throttleLimit int, backOffDuration time.Duration, incrementDuration time.Duration) Throttler {
	return BlockingThrottler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: incrementalBackoffFn(backOffDuration, incrementDuration),
	}
}

func incrementalBackoffFn(backOffDuration time.Duration, incrementDuration time.Duration) func(attempt int) {
	return func(attempt int) {
		sleepMillis := float64(backOffDuration.Milliseconds()) + math.Pow(float64(incrementDuration), float64(attempt))
		time.Sleep(time.Duration(sleepMillis) * time.Millisecond)
	}
}

func NewRandomisedBackoffThrottler(throttleLimit int, minDuration, maxDuration time.Duration) Throttler {
	return BlockingThrottler{
		limiter:   rate.NewLimiter(rate.Limit(throttleLimit), throttleLimit),
		onBackOff: randomisedBackoffFn(maxDuration, minDuration),
	}
}

func randomisedBackoffFn(maxDuration time.Duration, minDuration time.Duration) func(attempt int) {
	return func(attempt int) {
		randMillis := (rand.Int63() * (maxDuration.Milliseconds() - minDuration.Milliseconds())) + minDuration.Milliseconds()
		time.Sleep(time.Duration(randMillis) * time.Millisecond)
	}
}
{'fraction_non_alphanumeric': 0.10673502680027966, 'fraction_numerical': 0.005360055931018411, 'mean_word_length': 6.129568106312292, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '727838', 'n_tokens_mistral': 1529, 'n_tokens_neox': 1453, 'n_words': 268}