You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Perhaps this is an implementation issue. See the following file which shows the per second rate not working. If you set the rate limiter to 100 per second and you have 101 requests, it should take more than a second to finish since only 100/101 could have run in the first second and the last request would have to wait until the next second.
package main
import (
"context"
"github.com/go-redis/redis/v8"
"github.com/go-redis/redis_rate/v9"
"github.com/stretchr/testify/require"
"os"
"sync"
"sync/atomic"
"testing"
"time"
)
type Limiter interface {
Allow(ctx context.Context) (time.Duration, error)
}
type Rediser interface {
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd
ScriptExists(ctx context.Context, hashes ...string) *redis.BoolSliceCmd
ScriptLoad(ctx context.Context, script string) *redis.StringCmd
Del(ctx context.Context, keys ...string) *redis.IntCmd
}
func NewRedisLimiter(r Rediser, key string, perSec int) Limiter {
return &redisLimiter{
limiter: redis_rate.NewLimiter(r),
key: key,
perSec: perSec,
}
}
type redisLimiter struct {
limiter *redis_rate.Limiter
key string
perSec int
}
func (l *redisLimiter) Allow(ctx context.Context) (time.Duration, error) {
r, err := l.limiter.Allow(ctx, l.key, redis_rate.PerSecond(l.perSec))
if err != nil {
return 0, err
}
return r.RetryAfter, nil
}
func TestRedisLimiter_Allow(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
radd := os.Getenv("REDIS_ADDR") // set this in the env to host:port
opts := redis.Options{Addr: radd}
rc := redis.NewClient(&opts)
defer rc.Close()
perSecond := 100 // set the per second rate
var val int64
limiter := NewRedisLimiter(rc, "TestRedisLimiter_Allow", perSecond)
runs := perSecond + 1 // one more than the per second rate (last request should be in the next second)
wg := sync.WaitGroup{}
wg.Add(runs)
start := time.Now()
for i := 0; i < runs; i++ {
go func() {
defer wg.Done()
retryAfter, err := limiter.Allow(ctx)
require.NoError(t, err)
for retryAfter > 0 {
time.Sleep(retryAfter)
retryAfter, err = limiter.Allow(ctx)
require.NoError(t, err)
}
atomic.AddInt64(&val, 1)
}()
}
wg.Wait()
elapsed := time.Since(start)
require.GreaterOrEqual(t, elapsed, time.Second) // one more than the per second rate (last request should be in the next second)
require.Equal(t, runs, int(val))
}
Here is a docker-compose.yml that should be able to run the test via docker compose up test after go mod init && go mod tidy:
The only thing I can think of is that maybe the first second doesn't really count some how? I tried 100 per second for 1000 total and am getting a little over 9 seconds
The text was updated successfully, but these errors were encountered:
Perhaps this is an implementation issue. See the following file which shows the per second rate not working. If you set the rate limiter to 100 per second and you have 101 requests, it should take more than a second to finish since only 100/101 could have run in the first second and the last request would have to wait until the next second.
Here is a
docker-compose.yml
that should be able to run the test viadocker compose up test
aftergo mod init && go mod tidy
:The only thing I can think of is that maybe the first second doesn't really count some how? I tried 100 per second for 1000 total and am getting a little over 9 seconds
The text was updated successfully, but these errors were encountered: