Skip to content

Limiters

Daniel Pepper edited this page Mar 13, 2022 · 7 revisions

Berater::Limiter

The basic interface for all limiters.

.limit - acquire a lock. Raises a Berater::Overloaded error if limits have been exceeded. When passed a block, it will execute the block unless the limit has been exceeded. Otherwise it returns the lock, which should be released once completed.

  • capacity - override the limiter's capacity for this call
  • cost - the relative cost of this piece of work, default is 1

.utilization - a Float representing how much capacity is being used, as a fraction of the limit. Values >= 1 indicate that the limiter is overloaded and calls to .limit will fail.

limiter.limit(**opts) do
  # limited work
end

lock = limiter.limit
# do work inline, then manually release lock
lock.release

limiter.limit(cost: 2) do
# do extra expensive work
end

limiter.limit(capacity: 3) do
# do work within a different capacity limit
end

Berater::RateLimiter

Useful when you want to limit usage within a given time window. It uses the leaky bucket algorithm and supports millisecond level granularity.

Berater::RateLimiter.new(key, capacity, interval, **opts)
  • key - name of limiter
  • capacity - maximum number of requests permitted
  • interval - how often the capacity limit resets. Either number of seconds or a symbol: :second, :minute, :hour
  • opts
    • redis - a redis instance

eg. 2 times per second

limiter = Berater::RateLimiter.new(:key, 2, :second)
limiter.limit do
  # do work, twice per second
end

# or, more conveniently
Berater(:key, 2, interval: :second) do
  ...
end

Berater::ConcurrencyLimiter

Useful to limit the amount of work done concurrently, ie. simultaneously.

Berater::ConcurrencyLimiter.new(key, capacity, **opts)
  • key - name of limiter
  • capacity - maximum number of simultaneous requests
  • opts
    • timeout - maximum seconds a lock may be held (optional, but recommended)
    • redis - a redis instance

eg. no more than 3 connections at once

limiter = Berater::ConcurrencyLimiter.new(:key, 3, timeout: 30)
limiter.limit do
  # allow only three simultaneous requests at a time, for no more than 30 seconds each
end

# or, more conveniently
Berater(:key, 3, timeout: 30) do
  ...
end
Clone this wiki locally