AtomicBucket.FixedCostLimiter behaviour (atomic_bucket v0.5.1)

Copy Markdown View Source

Applies fixed cost limit: all requests to the same bucket use same (positive) cost.

Options

See __using__/1.

Examples

defmodule MyRateLimiter do
  use AtomicBucket.FixedCostLimiter
end

# application.ex
children = [.., MyRateLimiter, ..]

defmodule CallerModule do
  require MyRateLimiter

  MyRateLimiter.request(:mybucket, 1, 10, 3)
end

Summary

Functions

Converts the current module to a fixed cost rate limiter

Generated API

Checks if the request is allowed according to desired rate assuming all requests have same cost.

Starts AtomicBucket server managing buckets for the limiter.

Functions

__using__(opts \\ [])

(since 0.5.0) (macro)

Converts the current module to a fixed cost rate limiter:

  • generates rate limiter API

  • adds AtomicBucket server child spec so that the module can be added to a supervision tree

This macro does only basic validation of the cleanup parameters. Developers must ensure that buckets idling for more than ~24 days are deleted: longer periods are not supported by the wrapping timer used by the library.

Options:

  • :table ETS table name atom. By default is implementing module name.

  • :cleanup_interval interval in ms defining how often the server will try to delete idle buckets. It is applied on completion of a cleanup. Default is 1 hour.

  • :max_idle_period max period in ms since last bucket update before it is deleted by the server. Default is 24 hours.

  • persistent if true, bucket references will be cached in :persistent_term. Default is false.

Generated API

request(bucket_id, window, requests, burst, opts)

(since 0.5.0)
@macrocallback request(
  bucket_id :: any(),
  window :: pos_integer(),
  requests :: pos_integer(),
  burst :: pos_integer(),
  opts :: keyword()
) ::
  {:allow, requests :: non_neg_integer(), :atomics.atomics_ref()}
  | {:deny, timeout :: timeout(), :atomics.atomics_ref()}

Checks if the request is allowed according to desired rate assuming all requests have same cost.

The bucket is initialized in full state. Every request will refill the bucket if needed and check if the new token amount is enough to make the request. On success the request tokens are removed from the bucket and the function returns {:allow, requests, bucket_ref} where requests is the number of possible additional requests based on the remaining tokens in the bucket. Otherwise, the bucket is left untouched and the function returns {:deny, timeout, bucket_ref} where timeout is estimated period in ms after which the request may be allowed, according to the bucket state and the refill rate. bucket_ref is a reference to the bucket atomic.

Arguments:

  • bucket_id bucket id, unique within its table

  • window defines window in seconds

  • requests number of allowed requests in the window, according to the target rate. Together with window defines refill rate of the bucket

  • burst number of burst requests. Defines bucket capacity. Bursts ignore target request rate, and thus may significantly alter effective rate

Options:

  • ref bucket atomic reference. If provided, the call will try to use it instead of refetching.

start_link()

(since 0.5.0)
@callback start_link() :: GenServer.on_start()

Starts AtomicBucket server managing buckets for the limiter.

Normally users don't need to call this function directly - instead the implementing module can be added to a supervision tree and the server is then started by a supervisor.