Odo is a simple, GenServer based, token bucket rate limiter for communicating with rate limtied APIs. Full documentation can be found at https://hexdocs.pm/odo.
The package can be installed by adding odo
to your list of dependencies in mix.exs
:
def deps do
[{:odo, "~> 0.1.0"}]
end
you will also need to list it in your applications unless using Elixir ~> 1.4 which infers applications from your dependency list.
You can create a new bucket like so:
Odo.Bucket.new_bucket("my bucket")
and to obtain a token:
status = Odo.Bucket.get_token("my bucket")
The status return value will be one of the following forms. When it's ok to proceed with your request you will receive
{:go, tokens_remaining, until}
with until
being the time in milliseconds until he next tick or refill occurs.
When the bucket is full the reply will be {:stop, until}
, again with until
measured in milliseconds letting you know
when the next window of opportunity to make a request will open up.
You may also configure the bucket with the following options:
Odo.Bucket.new_bucket("my bucket", tokens: 20, tick_duration: 10_000, tick_refill_amount: 20, buffer: 200)
tick_duration: value
specifies the intervals at which the bucket is refilled in milliseconds whilst tick_refill_amount
provides for the amount to add in each tick. The buffer: value
lets you provide a buffer to add to the tick duration.
You may want to do that in order to account for latency or other delays between the time you secure a token from the bucket
and the time that the request to the remote API actually arrives.
For example, if you dispatch 10 requests within a 10 second window you can be sure that you do not exceed that amount, but you do not have a guarantee about when those requests are actually delivered to the remote service. If the latency between your client and the remote API varies, it is possible for a later request to arrive out of order and so fit within the earlier timing window of the remote service. This won't usually matter unless you're pushing close to the rate limit of the remote API.
In any event, matching the characteristics and quirks of the remote service will still mean having to guard against rate limiting restrictions in your own code.