Packages

A general throttle utility. Mainly used to throttle inbound or outbound requests.

Current section

Files

Jump to
throttle lib request.ex
Raw

lib/request.ex

defmodule Throttle.Request do
alias Throttle.Config
alias Throttle.Request
defstruct [
:started_at,
:namespace,
:keyspace,
:timespace,
:counter,
:count,
:limit,
:window,
:delay,
:delay_until,
allowed: true
]
def new({key, limit, window}) do
%Request{}
|> put_started_at
|> put_namespace
|> put_keyspace(key)
|> put_window(window)
|> put_limit(limit)
|> put_timespace
|> put_counter
end
def put_namespace(%Request{} = request) do
%{request | namespace: Config.get(:namespace, "throttle")}
end
def put_keyspace(%Request{} = request, key) do
%{request | keyspace: key}
end
def put_started_at(%Request{} = request) do
%{request | started_at: :os.system_time(:seconds)}
end
def put_window(%Request{} = request, :second) do
%{request | window: :second}
end
def put_window(%Request{} = request, :minute) do
%{request | window: :minute}
end
def put_window(%Request{} = request, :hour) do
%{request | window: :hour}
end
def put_limit(%Request{} = request, limit) when is_integer(limit) do
%{request | limit: limit}
end
def put_timespace(%Request{window: :second} = request) do
%{request | timespace: System.system_time(:second)}
end
def put_timespace(%Request{window: :minute} = request) do
%{request | timespace: Time.utc_now.minute}
end
def put_timespace(%Request{window: :hour} = request) do
%{request | timespace: Time.utc_now.hour}
end
def put_counter(%Request{namespace: ns, keyspace: ks, timespace: ts} = request) do
%{request | counter: "#{ns}/#{ks}/#{ts}"}
end
def put_count(%Request{} = request, count) do
%{request | count: count}
end
def put_allowed(%Request{count: count, limit: limit} = request) do
%{request | allowed: count <= limit}
end
def put_delay(%Request{allowed: true} = request), do: request
def put_delay(%Request{started_at: time, window: :second} = request) do
%{request | delay: 1, delay_until: time + 1 }
end
def put_delay(%Request{started_at: time, window: window} = request) do
next_window = time
|> DateTime.from_unix!
|> modify_datetime(window)
|> DateTime.to_unix
%{request | delay: next_window - time , delay_until: next_window }
end
defp modify_datetime(datetime, :minute) do
%{datetime | minute: datetime.minute + 1, second: 0}
end
defp modify_datetime(datetime, :hour) do
%{datetime | hour: datetime.min + 1, minute: 0}
end
end