Project

gcra

0.04
Low commit activity in last 3 years
A long-lived project that still receives updates
GCRA implementation for rate limiting
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 5.1
~> 3.12
 Project Readme

GCRA for Ruby

Build Status Code Climate RubyDoc

gcra is a Ruby implementation of a generic cell rate algorithm (GCRA), ported from and data-format compatible with the Go implementation throttled. It's useful for rate limiting (e.g. for HTTP requests) and allows weights specified per request.

Getting Started

gcra currently uses Redis (>= 2.6.12 for EVALSHA, SCRIPT LOAD, SEX with NX and PX) as a data store, although it supports other store implementations.

Add to your Gemfile:

gem 'gcra'
gem 'redis'

Create Redis, RedisStore and RateLimiter instances:

require 'redis'
require 'gcra/rate_limiter'
require 'gcra/redis_store'

redis = Redis.new(host: 'localhost', port: 6379, timeout: 0.1)
key_prefix = 'rate-limit-app1:'
store = GCRA::RedisStore.new(
          redis,
          key_prefix,
          { reconnect_on_readonly: false },
        )

rate_period = 0.5  # Two requests per second
max_burst = 10     # Allow 10 additional requests as a burst
limiter = GCRA::RateLimiter.new(store, rate_period, max_burst)
  • rate_period: Period between two requests, allowed as a sustained rate. Example: 0.1 for 10 requests per second
  • max_burst: Number of requests allowed as a burst in addition to the sustained rate. If the burst is used up, one additional request allowed as burst 'comes back' after each rate_period where no request was made.

Rate limit a request (call this before each request):

key = '123'  # e.g. an account identifier
quantity = 1  # the number of requests 'used up' by this request, useful e.g. for batch requests

exceeded, info = limiter.limit(key, quantity)
# => [false, #<struct GCRA::RateLimitInfo limit=11, remaining=10, reset_after=0.5, retry_after=nil>]
  • exceeded: false means the request should be allowed, true means the request would exceed the limit and should be blocked.
  • info: GCRA::RateLimitInfo contains information that might be useful for your API users. It's a Struct with the following fields:
    • limit: Contains the number of requests that can be made if no previous requests have been made (or they were long enough ago). That's max_burst plus one. The latter is necessary so requests are allowed at all when max_burst is set to zero.
    • remaining: The number of remaining requests that can be made immediately, i.e. the remaining burst.
    • reset_after: The time in seconds until the full burst will be available again.
    • retry_after: Set to nil if a request is allowed or it otherwise doesn't make sense to retry a request (if quantity is larger than max_burst). For a blocked request that can be retried later, set to the duration in seconds until the next request with the given quantity will be allowed.

RateLimiter#limit only tells you whether to limit a request or not. You'll have to react to its response yourself and e.g. return an error message and stop processing a request if the limit was exceeded.

License

MIT