View Source Leaky (Leaky v0.1.1)

Implements a token-based rate limiter using the leaky bucket algorithm, ideal for controlling access rates to resources in Elixir applications. This implementation leverages ETS for optimized performance, making it suitable for high-load environments.

Overview

The leaky bucket algorithm helps smooth out bursty traffic by limiting the rate at which actions are taken. It's like a bucket with a hole: tokens, representing permissions to take an action, drip out at a constant rate. If the bucket is full, new actions must wait, ensuring the overall rate does not exceed the desired threshold. Read more about the algorithm here: https://en.wikipedia.org/wiki/Leaky_bucket

Usage

The rate limiter process can be customized with several options:

  • bucket_name: Unique identifier for the bucket.
  • max_accumulated: The maximum tokens the bucket can hold. Once full, new tokens will not accumulate.
  • refill: The number of tokens added to the bucket on each refill cycle.
  • interval: The time (in ms) between each refill cycle. Defaults to 1000 ms.
  • name: The GenServer process name. Defaults to Leaky.
  configuration = [bucket_name: :user_requests, max_accumulated: 100, refill: 10, interval: 1000]
  {:ok, _pid} = Leaky.start_link(configuration)

To attempt an action, checking if it's allowed under the current rate:

  case Leaky.acquire(:user_requests, 1) do
    {:allow, tokens_left} -> "Action allowed."
    :deny ->"Action denied."
  end

Summary

Functions

The function evaluates whether a particular action can proceed without violating the configured rate limit of the bucket. It is designed to ensure that the frequency of actions does not exceed the predetermined limits, thus preventing system overload or abuse.

The function adjusts the number of tokens in a specified bucket by either adding (incrementing) or removing (decrementing) tokens, directly influencing the bucket's current capacity without performing a rate check.

Returns a specification to start this module under a supervisor.

The function retrieves the current number of available tokens in the specified bucket, providing insight into the bucket's current state without altering it. It accepts the bucket identifier and an optional name parameter for the GenServer managing the rate limiter's state, returning either the number of tokens left or nil if the bucket does not exist. This function is useful for monitoring and debugging purposes, allowing developers to assess the rate limiter's status at any given moment.

Updates the configuration of the rate limiter process. Changes are applied immediately, affecting the rate limiter's behavior. It is useful for dynamically adjusting the rate limiter's settings without restarting the process.

Types

@type bucket() :: integer() | binary() | tuple() | atom()

Functions

Link to this function

acquire(bucket, cost, name \\ __MODULE__)

View Source
@spec acquire(bucket :: bucket(), cost :: integer(), name :: GenServer.name()) ::
  {:allow, integer()} | :deny

The function evaluates whether a particular action can proceed without violating the configured rate limit of the bucket. It is designed to ensure that the frequency of actions does not exceed the predetermined limits, thus preventing system overload or abuse.

Examples

.  case Leaky.acquire(:user_requests, 1) do
    {:allow, tokens_left} -> "Action allowed."
    :deny ->"Action denied."
  end
Link to this function

adjust_tokens(bucket, amount, name \\ __MODULE__)

View Source
@spec adjust_tokens(bucket :: bucket(), amount :: integer(), name :: GenServer.name()) ::
  :ok

The function adjusts the number of tokens in a specified bucket by either adding (incrementing) or removing (decrementing) tokens, directly influencing the bucket's current capacity without performing a rate check.

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

inspect(bucket, name \\ __MODULE__)

View Source
@spec inspect(bucket :: bucket(), name :: GenServer.name()) :: integer() | nil

The function retrieves the current number of available tokens in the specified bucket, providing insight into the bucket's current state without altering it. It accepts the bucket identifier and an optional name parameter for the GenServer managing the rate limiter's state, returning either the number of tokens left or nil if the bucket does not exist. This function is useful for monitoring and debugging purposes, allowing developers to assess the rate limiter's status at any given moment.

Example

 iex> Leaky.inspect(:user_requests)
 iex> 3
Link to this function

update_configuration(opts, name \\ __MODULE__)

View Source
@spec update_configuration(opts :: Keyword.t(), name :: GenServer.name()) :: :ok

Updates the configuration of the rate limiter process. Changes are applied immediately, affecting the rate limiter's behavior. It is useful for dynamically adjusting the rate limiter's settings without restarting the process.

Options which can be updated: max_accumulated, interval, and refill.

Example

iex> Leaky.update_configuration(max_accumulated: 10, refill: 2, interval: 5)
:ok
iex> {:allow, 8} == Leaky.acquire(:user_requests, 2)
true