Limiter

Build Status

Rate limiter implementation of Generic Cell Rate Algorithm (GCRA).

For detailed information on how the algorithm works, please check the following links:

The implementation is similar to Go throttled library:

Installation

If available in Hex, the package can be installed as:

  1. Add limiter to your list of dependencies in mix.exs:

    def deps do
      [{:limiter, "~> 0.1.1"}]
    end
  2. Ensure limiter is started before your application:

    def application do
      [applications: [:limiter]]
    end

Usage

First off, a storage must be configured and started. Currently, the rate limiter supports one implementation of the storage, which is Limiter.Storage.ConCache. Each implementation of the storage can have different options.

The storage can be started in two ways:

  • as a part of the limiter’s supervision tree - the config of the limiter’s storage is in the config file. For example:

    config :limiter,
      storage: [{Limiter.Storage.ConCache, :limiter_con_cache}]
    
    config :limiter, :limiter_con_cache,
      ttl_check: 1_000
  • as a part of the supervision tree of the application which is using the limiter (so the storage can be restarted with that application) - Limiter.Storage.ConCache exports start_link/1 function, so it can be added to the supervision tree, for example:

    children = [
      ...
      worker(Limiter.Storage.ConCache, [
        [name: :limiter_con_cache, ttl_check: 1_000]
      ])
    ]
    ...
    Supervisor.start_link(children, ...)

The Limiter module exports checkout/5 with the following arguments:

  • storage - tuple that contains the module used for storage (Limiter.Storage.ConCache) and options for the given storage.
  • key - the key associated with an action which is rate limited.
  • quantity - the weight of an action. Typically it’s set to 1. The more expensive actions may use greater value.
  • period - the period of time that along with limit defines the rate limit.
  • limit - the number of actions (in case the quantity is 1) that along with the period defines the rate limit.

Example:

Limiter.checkout({Limiter.Storage.ConCache, :limiter_con_cache}, "key", 1, 10_000, 5)

The Limiter.checkout/5 functions returns a struct (Limiter.Result) with the following information:

  • allowed - indicates if an action is allowed or rate limited.
  • remaining - the number of actions that is allowed before reaching the rate limit.
  • reset_after - how long (in milliseconds) it will take for the given key to get to the initial state.
  • retry_after - how long (in milliseconds) it will take for the next action (associated with the given key) to be allowed.