This gem is an implementation of GCRA for rate limiting based on Redis.
The code requires Redis version 3.2 or newer since it relies on
replicate_commands
feature.
gem "redis-gcra"
And then execute:
$ bundle
Or install it yourself as:
$ gem install redis-gcra
In order to perform rate limiting, you need to call the limit
method.
In this example the rate limit bucket has 1000 tokens in it and recovers at speed of 100 tokens per minute.
redis = Redis.new
result = RedisGCRA.limit(
redis: redis,
key: "overall-account/bob@example.com",
burst: 1000,
rate: 100,
period: 60, # seconds
cost: 2
)
result.limited? # => false - request should not be limited
result.remaining # => 998 - remaining number of requests until limited
result.retry_after # => nil - can retry without delay
result.reset_after # => ~0.6 - in 0.6 seconds rate limiter will completely reset
# call limit 499 more times in rapid succession and you get:
result.limited? # => true - request should be limited
result.remaining # => 0 - no requests can be made at this point
result.retry_after # => ~1.2 - can retry in 1.2 seconds
result.reset_after # => ~600 - in 600 seconds rate limiter will completely reset
The implementation utilizes single key in Redis that matches the key you pass
to the limit
method. If you need to reset rate limiter for particular key,
just delete the key from Redis:
# Let's imagine `overall-account/bob@example.com` is limited.
# This will effectively reset limit for the key:
redis.del "overall-account/bob@example.com"
You call also retrieve the current state of rate limiter for particular key
without actually modifying the state. In order to do that, use the peek
method:
result = RedisGCRA.peek(
redis: redis,
key: "overall-account/bob@example.com",
burst: 1000,
rate: 100,
period: 60 # seconds
)
result.limited? # => true - current state is limited
result.remaining # => 0 - no requests can be made
result.retry_after # => ~0.6 - in 0.6 seconds remaining will become 1
result.reset_after # => ~600 - in 600 seconds rate limiter will completely reset
This code was inspired by this great blog post by Brandur Leach and his amazing work on throttled Go package.
The gem is available as open source under the terms of the MIT License.