registry/ratelimiter/ratelimiter.go (41 lines of code) (raw):

package ratelimiter import ( "context" "time" "github.com/docker/distribution/configuration" "github.com/docker/distribution/internal/redis_rate" "github.com/redis/go-redis/v9" ) // Limiter implements handlers.RateLimiter using Redis as the backend. type Limiter struct { client *redis_rate.Limiter config *configuration.Limiter } // Result obtained from the Redis rate limiting algorithm. type Result struct { Allowed int Remaining int RetryAfter time.Duration } // New creates a new rate limiter instance. func New(client redis.UniversalClient, config *configuration.Limiter) *Limiter { return &Limiter{ client: redis_rate.NewLimiter(client), config: config, } } // Allowed checks if the specified key is allowed to perform the action based on the configured rate limit. func (rl *Limiter) Allowed(ctx context.Context, key string) (*Result, error) { res, err := rl.client.Allow(ctx, key, redis_rate.Limit{ Rate: int(rl.config.Limit.Rate), Burst: int(rl.config.Limit.Burst), Period: rl.config.Limit.PeriodDuration, }) if err != nil { return nil, err } return &Result{ Allowed: res.Allowed, Remaining: res.Remaining, RetryAfter: res.RetryAfter, }, nil } // Config returns the configuration of this rate limiter. func (rl *Limiter) Config() *configuration.Limiter { return rl.config }