Reuse previous instance within rate-limit interval

Rather than blocking <1s back-to-back queries from the same IP, Farside
will now re-use the previously selected instance.

Fixes #20
This commit is contained in:
Ben Busby 2022-03-18 13:51:37 -06:00
parent 20347822da
commit 22e9135e0c
No known key found for this signature in database
GPG key ID: B9B7231E01D924A1
3 changed files with 20 additions and 11 deletions

View file

@ -26,6 +26,15 @@ defmodule Farside do
end)
end
def last_instance(service) do
{:ok, previous} =
Redix.command(
:redix,
["GET", "#{service}#{@previous_suffix}"]
)
previous
end
def pick_instance(service) do
{:ok, instances} =
Redix.command(
@ -38,7 +47,7 @@ defmodule Farside do
]
)
# Either pick a random available instance,
# Either pick a random available instance,
# or fall back to the default one
instance =
if Enum.count(instances) > 0 do
@ -48,14 +57,8 @@ defmodule Farside do
else
# ...otherwise pick a random one from the list, ensuring
# that the same instance is never picked twice in a row.
{:ok, previous} =
Redix.command(
:redix,
["GET", "#{service}#{@previous_suffix}"]
)
instance =
Enum.filter(instances, &(&1 != previous))
Enum.filter(instances, &(&1 != last_instance(service)))
|> Enum.random()
Redix.command(

View file

@ -40,7 +40,14 @@ defmodule Farside.Router do
get "/:service/*glob" do
path = Enum.join(glob, "/")
instance = Farside.pick_instance(service)
instance = cond do
conn.assigns[:throttle] != nil ->
Farside.last_instance(service)
true ->
Farside.pick_instance(service)
end
IO.inspect(get_req_header(conn, "throttle"))
IO.inspect(instance)
params =
cond do

View file

@ -14,8 +14,7 @@ defmodule Farside.Throttle do
def allow_action(conn, _data, _opts), do: conn
def block_action(conn, _data, _opts) do
conn = assign(conn, :throttle, 1)
conn
|> send_resp(:forbidden, "Exceeded rate limit\n")
|> halt
end
end