diff --git a/lib/pleroma/http/backoff.ex b/lib/pleroma/http/backoff.ex index e7f7cf234..20edeae42 100644 --- a/lib/pleroma/http/backoff.ex +++ b/lib/pleroma/http/backoff.ex @@ -28,8 +28,7 @@ def get(url, headers \\ [], options \\ []) do # this ensures that we don't hammer the server with requests, and instead wait for the backoff to expire # this is a very simple implementation, and can be improved upon! %{host: host} = URI.parse(url) - - case @cachex.get(@backoff_cache, host) do + case @cachex.get(@backoff_cache, host) do {:ok, nil} -> case HTTP.get(url, headers, options) do {:ok, env} -> @@ -38,8 +37,7 @@ def get(url, headers \\ [], options \\ []) do Logger.error("Rate limited on #{host}! Backing off...") timestamp = next_backoff_timestamp(env) ttl = Timex.diff(timestamp, DateTime.utc_now(), :seconds) - # we will cache the host for 5 minutes - @cachex.put(@backoff_cache, host, true, ttl) + @cachex.put(@backoff_cache, host, true, ttl: ttl) {:error, env} _ -> diff --git a/test/pleroma/http/backoff_test.exs b/test/pleroma/http/backoff_test.exs new file mode 100644 index 000000000..e8a571e87 --- /dev/null +++ b/test/pleroma/http/backoff_test.exs @@ -0,0 +1,34 @@ +defmodule Pleroma.HTTP.BackoffTest do + @backoff_cache :http_backoff_cache + use Pleroma.DataCase, async: false + alias Pleroma.HTTP.Backoff + + describe "get/3" do + test "should return {:ok, env} when not rate limited" do + Tesla.Mock.mock_global(fn + %Tesla.Env{url: "https://akkoma.dev/api/v1/instance"} -> + {:ok, %Tesla.Env{status: 200, body: "ok"}} + end) + assert {:ok, env} = Backoff.get("https://akkoma.dev/api/v1/instance") + assert env.status == 200 + end + + test "should return {:error, env} when rate limited" do + # Shove a value into the cache to simulate a rate limit + Cachex.put(@backoff_cache, "akkoma.dev", true) + assert {:error, env} = Backoff.get("https://akkoma.dev/api/v1/instance") + assert env.status == 429 + end + + test "should insert a value into the cache when rate limited" do + Tesla.Mock.mock_global(fn + %Tesla.Env{url: "https://ratelimited.dev/api/v1/instance"} -> + {:ok, %Tesla.Env{status: 429, body: "Rate limited"}} + end) + + assert {:error, env} = Backoff.get("https://ratelimited.dev/api/v1/instance") + assert env.status == 429 + assert {:ok, true} = Cachex.get(@backoff_cache, "ratelimited.dev") + end + end +end