diff --git a/pkg/pacing/interceptor.go b/pkg/pacing/interceptor.go index 210f6d88..392a1b24 100644 --- a/pkg/pacing/interceptor.go +++ b/pkg/pacing/interceptor.go @@ -177,12 +177,11 @@ type Interceptor struct { // burst calculates the minimal burst size required to reach the given rate and // pacing interval. func burst(rate int, interval time.Duration) int { - if interval == 0 { + if interval <= 0 { interval = time.Millisecond } - f := float64(time.Second.Milliseconds() / interval.Milliseconds()) - return max(8*1500, int(float64(rate)/f)) + return max(8*1500, int(float64(rate)*interval.Seconds())) } // setRate updates the pacing rate and burst of the rate limiter. diff --git a/pkg/pacing/interceptor_test.go b/pkg/pacing/interceptor_test.go index 27f4958f..d31eb26c 100644 --- a/pkg/pacing/interceptor_test.go +++ b/pkg/pacing/interceptor_test.go @@ -55,6 +55,31 @@ func (m *mockPacer) SetRate(rate int, burst int) { m.burst = burst } +func TestBurst(t *testing.T) { + const minBurst = 8 * 1500 + + for _, cc := range []struct { + name string + rate int + interval time.Duration + expected int + }{ + {"sub_millisecond_interval", 1_000_000, 500 * time.Microsecond, minBurst}, + {"sub_millisecond_interval_high_rate", 100_000_000, 500 * time.Microsecond, 50_000}, + {"zero_interval_defaults_to_1ms", 100_000_000, 0, 100_000}, + {"negative_interval_defaults_to_1ms", 100_000_000, -time.Second, 100_000}, + {"rate_below_min_burst", 300_000, 5 * time.Millisecond, minBurst}, + {"divides_evenly", 3_000_000, 5 * time.Millisecond, 15_000}, + {"does_not_divide_evenly", 3_000_000, 7 * time.Millisecond, 21_000}, + {"long_interval", 3_000_000, 33 * time.Millisecond, 99_000}, + {"zero_rate", 0, 5 * time.Millisecond, minBurst}, + } { + t.Run(cc.name, func(t *testing.T) { + assert.Equal(t, cc.expected, burst(cc.rate, cc.interval)) + }) + } +} + func TestInterceptor(t *testing.T) { t.Run("calls_set_rate", func(t *testing.T) { mp := &mockPacer{}