Ralitobu

The Rate Limiter with Token Bucket algorithm

This is a fork of ExRated, but with some changes:

  • the checkout and inspection always return the same result tuple
  • asynchronous counterparts for checkout, inspect and delete
  • configuration can be given on initialization and not only via application environment (useful when starting multiple rate limiters with different settings)

Installation

In mix.exs:

  def deps do
    [{:ralitobu, "~> 0.1.0"}]
  end
  def application do
    [applications: [:ralitobu]]
  end

Usage

Checkouts

The result tuple format:

{success, counter, remaining_limit, total_limit, countdown, created_at, updated_at}
# 1st call:
Ralitobu.checkout("my-bucket", 3, 10_000)
#=> {:ok, 1, 2, 3, 7806, 1461432862194, 1461432862194}

# 3rd call:
Ralitobu.checkout("my-bucket", 3, 10_000)
#=> {:ok, 3, 0, 3, 7799, 1461432862194, 1461432862201}

# 4th call fails (over rate limit):
Ralitobu.checkout("my-bucket", 3, 10_000)
#=> {:error, 3, 0, 3, 7795, 1461432862194, 1461432862200}

Inspection

The result tuple format:

{success, counter, remaining_limit, total_limit, countdown, created_at, updated_at}
# multiple calls do not increment the counter:
Ralitobu.inspect("my-bucket", 3, 10_000)
#=> {:ok, 2, 3, 3, 4132, 1461432862194, 1461432862200}
Ralitobu.inspect("my-bucket", 3, 10_000)
#=> {:ok, 2, 3, 3, 4130, 1461432862194, 1461432862200}

# bucket does not exists:
Ralitobu.inspect("my-other-bucket", 3, 10_000)
#=> {:ok, 0, 3, 3, 9142, nil, nil}

Deletion

Result is either :ok or :error, depending if the bucket existed or not.

# bucket (still) exists:
Ralitobu.delete("my-bucket")
#=> :ok

# bucket is not present (anymore):
Ralitobu.delete("my-bucket")
#=> :error

New server instance

The application always starts a default server, but you can run your own instance(s) as well.

Ralitobu.start_server/2 (Ralitobu.start_server(configuration, gen_server_opts))

{:ok, server} = Ralitobu.start_server(
  [table_name: :another_ralitobu_table, timeout: 30_000_000, cleanup_rate: 15_000],
  [name: :another_ralitobu_server]
)

You must provide the name parameter for the GenServer options, otherwise it will take the default name and therefore not starting a new server. Also the table_name must be different, too.

Server configuration

  • table_name (atom): The name of the ETS table
  • timeout (integer): milliseconds; buckets older than (now - timeout) will be cleaned up (based on last update timestamp)
  • cleanup_rate (integer): milliseconds; the interval for the clean up task