mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
**What changed?** `DynamicRateLimiterImpl.Rate()` and `Burst()` now call `maybeRefresh()` before returning the underlying limiter values. **Why?** `DynamicRateLimiterImpl` already refreshes before token operations such as `Allow`, `Reserve`, and `Wait`, but direct `Rate()` / `Burst()` calls could keep returning stale cached values after the refresh interval. This matters when a dynamic rate limiter is used through the `RateBurst` surface, which was called out as a follow-up in #4934. Fixes #4934. **How did you test it?** ```bash GOWORK=off GOCACHE=/tmp/go-build-cache go test ./common/quotas GOWORK=off GOCACHE=/tmp/go-build-cache go test ./common/quotas -run TestDynamicRateLimiterRateAndBurstRefreshAfterInterval -count=20 GOWORK=off GOCACHE=/tmp/go-build-cache go test -race ./common/quotas -run TestDynamicRateLimiterRateAndBurstRefreshAfterInterval -count=20 ``` **Potential risks** Low. This makes getter behavior consistent with existing dynamic limiter token operations. The refresh path is already used by the limiter's main operation methods. **Is hotfix candidate?** No.
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package quotas_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"go.temporal.io/server/common/quotas"
|
|
)
|
|
|
|
func TestDynamicRateLimiterRateAndBurstRefreshAfterInterval(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const (
|
|
refreshInterval = 50 * time.Millisecond
|
|
initialRate = 10.0
|
|
initialBurst = 20
|
|
updatedRate = 30.0
|
|
updatedBurst = 40
|
|
nextRate = 50.0
|
|
nextBurst = 60
|
|
)
|
|
|
|
t.Run("rate_refreshes_without_token_operation", func(t *testing.T) {
|
|
rateBurst := quotas.NewMutableRateBurst(initialRate, initialBurst)
|
|
limiter := quotas.NewDynamicRateLimiter(rateBurst, refreshInterval)
|
|
|
|
require.InDelta(t, initialRate, limiter.Rate(), 1e-9)
|
|
|
|
rateBurst.SetRPS(updatedRate)
|
|
rateBurst.SetBurst(updatedBurst)
|
|
|
|
require.Eventually(t, func() bool {
|
|
return limiter.Rate() == updatedRate
|
|
}, time.Second, 5*time.Millisecond)
|
|
|
|
rateBurst.SetRPS(nextRate)
|
|
rateBurst.SetBurst(nextBurst)
|
|
|
|
require.InDelta(t, updatedRate, limiter.Rate(), 1e-9)
|
|
})
|
|
|
|
t.Run("burst_refreshes_without_token_operation", func(t *testing.T) {
|
|
rateBurst := quotas.NewMutableRateBurst(initialRate, initialBurst)
|
|
limiter := quotas.NewDynamicRateLimiter(rateBurst, refreshInterval)
|
|
|
|
require.Equal(t, initialBurst, limiter.Burst())
|
|
|
|
rateBurst.SetRPS(updatedRate)
|
|
rateBurst.SetBurst(updatedBurst)
|
|
|
|
require.Eventually(t, func() bool {
|
|
return limiter.Burst() == updatedBurst
|
|
}, time.Second, 5*time.Millisecond)
|
|
|
|
rateBurst.SetRPS(nextRate)
|
|
rateBurst.SetBurst(nextBurst)
|
|
|
|
require.Equal(t, updatedBurst, limiter.Burst())
|
|
})
|
|
}
|