traffic_jam

by coinbase

coinbase / traffic_jam

DEPRECATED — Ruby library for time-based rate limiting

127 Stars 11 Forks Last release: Not found MIT License 66 Commits 0 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

TrafficJam

Build Status Coverage Status

This is a library for enforcing rate limits across concurrent processes. This can be used to cap the number of actions that may be performed in a certain period of time. More generally, this can be used to enforce a cap on an integer amount that can be incremented or decremented. A limit consists of an action name, a maximum amount, and a period of time in seconds.

Instead of guaranteeing that the number of actions will never exceed the cap the given timeframe, the approach we take is to use a continuously regenerating limit. The amount remaining will constantly increase at a rate of max / period until it hits the cap. If, for example, the limit is 60 per minute, a user could increment by 60 at once, then increment by 1 per second forever without hitting the cap. As a consequence, this algorithm guarantees that the total amount incremented will be less than twice the limit in any given timeframe.

Usage

require 'traffic_jam'

TrafficJam.configure do |config| config.redis = Redis.new(url: REDIS_URL) end

limit = TrafficJam::Limit.new( :requests_per_user, user.id, max: 3, period: 1 # seconds ) limit.increment # => true limit.increment(2) # => true limit.increment # => false limit.increment! # => raises TrafficJam::LimitExceededError

sleep 1

limit.increment(2) # => true limit.exceeded? # => false limit.exceeded?(2) # => true

limit.used # => 2 limit.remaining # => 1

Configuration

TrafficJam configuration object can be accessed with

TrafficJam.config
or in a block like
TrafficJam.configure { |config| ... }
. Configuration options are:

redis (required): A Redis instance to store amounts used for each limit.

key_prefix (default: "traffic_jam"): The string prefixing all keys in Redis.

Registering limits

Fixed limits can be registered for a key if the cap does not change depending on the value. All instance methods are available on the class.

TrafficJam.configure do |config|
  config.register(:requests_per_user, 3, 1)
end

limit = TrafficJam.limit(:requests_per_user, "user1") limit.increment(2) # => true

TrafficJam.increment(:requests_per_user, "user1", 1) # => true TrafficJam.used(:requests_per_user, "user1") # => 3

Changing cap for a limit

Given an instance of

TrafficJam::Limit
with a maximum cap and a period, the behavior is to increase the amount remaining at a rate of max / period since the last time
increment
was called for the given value. If the cap is defined on a per-value basis, it is good practice to call
increment(0)
if the limit changes.

For example:

user.requests_per_hour = 10

limit = TrafficJam::Limit.new( :requests_per_user, user.id, max: user.requests_per_hour, period: 60 * 60 ) limit.increment(8) # => true

sleep 60

limit.increment(0)

user.requests_per_hour = 20 limit = TrafficJam::Limit.new( :requests_per_user, user.id, max: user.requests_per_hour, period: 60 * 60 ) limit.increment(8) # => true

Running tests

The

REDIS_URI
environment variable can be set in tests, and defaults to
redis://localhost:6379
.
rake test

To run a performance/stress test, see the

test/stress.rb
script.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.