Git Product home page Git Product logo

gcra-ruby's Introduction

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

gcra-ruby's People

Contributors

brasic avatar forsbergplustwo avatar martinseener avatar mfrister avatar tobischo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gcra-ruby's Issues

Problem with quantity

Here is my simple throttling code:

limiter = GCRA::RateLimiter.new(
      GCRA::RedisStore.new($redis, "test"),
      1 / 10.0,
      0
    )
limiter.limit('all', 1)
=> [false, #<struct GCRA::RateLimitInfo limit=1, remaining=0, reset_after=0.1, retry_after=nil>]
limiter.limit('all', 2)
=> [true, #<struct GCRA::RateLimitInfo limit=1, remaining=1, reset_after=0.0, retry_after=nil>]

It all works fine with quantity 1, but when I set different value, it returns inconsistent result.
The "true" is returned as exceeded, but the retry_after is nil and also "remaining" is a positive value.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.