AtomicBucket (atomic_bucket v0.2.0)

Copy Markdown View Source

Fast single node rate limiter implementing Token Bucket algorithm.

Summary

Functions

Returns a specification to start this module under a supervisor.

Checks if the request is allowed according to bucket parameters. Differences from request/5

Checks if the request is allowed according to desired request rate.

Starts the process that manages ETS table for bucket data and periodically deletes idle buckets.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

raw_request(bucket, capacity, refill_ms, cost, opts \\ [])

(macro)
@spec raw_request(
  bucket :: any(),
  capacity :: pos_integer(),
  refill_ms :: pos_integer(),
  cost :: integer(),
  opts :: keyword()
) :: {:allow | :deny, tokens :: non_neg_integer(), :atomics.atomics_ref()}

Checks if the request is allowed according to bucket parameters. Differences from request/5:

  • direct control of bucket parameters (less ergonomic but more powerful)
  • always returns remaining tokens
  • supports variable cost
  • supports negative cost, i.e. "refunds"
  • because of token accounting refills the bucket on every call (eager refill), while request/5 skips it for denied requests (lazy refill)

The bucket is initialized in full state. Every request will refill the bucket if needed and check if the new token amount with the cost applied is valid (not negative). Tokens above the capacity are discarded.

Returns {:allow, tokens, bucket_ref} or {:deny, tokens, bucket_ref} where tokens is the number of remaining tokens in the bucket.

Arguments:

  • bucket bucket id, unique within its table
  • capacity bucket capacity
  • refill_ms number of tokens added to the bucket every millisecond
  • cost number of tokens added or removed from the bucket for the current request to succeed, where negative values mean addition.

Supports same options as request/5

request(bucket, window, window_requests, burst_requests, opts \\ [])

(macro)
@spec request(
  bucket :: any(),
  window :: pos_integer(),
  window_requests :: pos_integer(),
  burst_requests :: pos_integer(),
  opts :: keyword()
) ::
  {:allow, bucket_requests :: non_neg_integer(), :atomics.atomics_ref()}
  | {:deny, timeout :: timeout(), :atomics.atomics_ref()}

Checks if the request is allowed according to desired request rate.

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 bucket id, unique within its table
  • window defines window in seconds
  • window_requests number of allowed requests in the window, according to the target rate. Together with window defines refill rate of the bucket.
  • burst_requests number of burst requests. Defines bucket capacity. Bursts ignore target request rate, and thus may significantly alter effective rate.

Supported options:

  • persistent if true, the bucket reference is also cached in :persistent_term. Default is false.

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

  • table ETS table name atom. Default is AtomicBucket.

start_link(opts)

Starts the process that manages ETS table for bucket data and periodically deletes idle buckets.

The function 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.

In addition to standard GenServer options, accepts the following:

  • :cleanup_interval interval in ms defining how often the server will try to delete idle buckets. Default is 1 hour.

  • :max_idle_period max period in ms since last allowed request before the bucket is deleted. Default is 24 hours.

  • table ETS table name atom. Default is AtomicBucket.