Skip to content

Commit

Permalink
improve ratelimit handling
Browse files Browse the repository at this point in the history
* rename some methods to be more accurate
* handle the requests synchronously
* general code improvements for readability
  • Loading branch information
Kraigie committed Feb 22, 2018
1 parent 22132a0 commit cb85fe0
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 33 deletions.
30 changes: 14 additions & 16 deletions lib/nostrum/api/bucket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ defmodule Nostrum.Api.Bucket do

alias Nostrum.Util

def create_bucket(route, remaining, reset_time, latency) do
def update_bucket(route, remaining, reset_time, latency) do
:ets.insert(:ratelimit_buckets, {route, remaining, reset_time, latency})
end

def lookup_bucket(route) do
route_time = :ets.lookup(:ratelimit_buckets, route)
global_time = :ets.lookup(:ratelimit_buckets, "GLOBAL")

Enum.max([route_time, global_time])
Enum.max_by([route_time, global_time], fn info ->
case info do
[] -> -1
[{_route, _remaining, reset_time, _latency}] -> reset_time
end
end)
end

def update_bucket(route, remaining) do
def update_remaining(route, remaining) do
:ets.update_element(:ratelimit_buckets, route, {2, remaining})
end

Expand All @@ -25,19 +30,12 @@ defmodule Nostrum.Api.Bucket do
def get_ratelimit_timeout(route) do
case lookup_bucket(route) do
[] ->
:none
[{route, remaining, reset_time, latency}] when remaining <= 0 ->
update_bucket(route, remaining - 1)
wait_time = reset_time - Util.now + latency
if wait_time <= 0 do
delete_bucket(route)
nil
else
wait_time
end
[{route, remaining, _reset_time, _latency}] ->
update_bucket(route, remaining - 1)
nil
:now
[{route, remaining, _reset_time, _latency}] when remaining > 0 ->
update_remaining(route, remaining - 1)
:now
[{_route, _remaining, reset_time, latency}] ->
reset_time - Util.now + latency
end
end

Expand Down
25 changes: 8 additions & 17 deletions lib/nostrum/api/ratelimiter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,10 @@ defmodule Nostrum.Api.Ratelimiter do
|> Bucket.get_ratelimit_timeout

case retry_time do
# No wait time, delegate to task
nil ->
Task.start(fn ->
GenServer.reply(original_from || from, do_request(request))
end)
# No rl data, block requests until rl data obtained
:none ->
:now ->
GenServer.reply(original_from || from, do_request(request))
time when time < 0 ->
GenServer.reply(original_from || from, do_request(request))
# Wait time found, delegate to task to retry
time ->
Task.start(fn ->
wait_for_timeout(request, time, original_from || from)
Expand Down Expand Up @@ -89,22 +84,18 @@ defmodule Nostrum.Api.Ratelimiter do

latency = abs(origin_timestamp - Util.now)

if global_limit do
update_global_bucket(route, 0, retry_after, latency)
else
update_bucket(route, remaining, reset, latency)
end

if global_limit, do: update_global_bucket(route, 0, retry_after, latency)
if reset, do: update_bucket(route, remaining, reset, latency)

response
end

defp update_bucket(_route, remaining, _time, _latency) when is_nil(remaining), do: nil
defp update_bucket(route, remaining, reset_time, latency) do
Bucket.create_bucket(route, remaining, reset_time * 1000, latency)
Bucket.update_bucket(route, remaining, reset_time * 1000, latency)
end

defp update_global_bucket(_route, _remaining, retry_after, latency) do
Bucket.create_bucket("GLOBAL", 0, retry_after + Util.now, latency)
Bucket.update_bucket("GLOBAL", 0, retry_after + Util.now, latency)
end

defp wait_for_timeout(request, timeout, from) do
Expand Down

0 comments on commit cb85fe0

Please sign in to comment.