diff options
author | rinpatch <rinpatch@sdf.org> | 2020-02-28 17:35:01 +0300 |
---|---|---|
committer | rinpatch <rinpatch@sdf.org> | 2020-03-01 01:13:07 +0300 |
commit | 4d416343fae4a9e0b1654b12bd476017be63a7e9 (patch) | |
tree | 272e3a611db85c2344f553f0e956cafaae27d4be /lib | |
parent | df2173343accec7a7a311d85df2f13d5141b7bc7 (diff) | |
download | pleroma-4d416343fae4a9e0b1654b12bd476017be63a7e9.tar.gz pleroma-4d416343fae4a9e0b1654b12bd476017be63a7e9.zip |
rate limiter: Fix a race condition
When multiple requests are processed by rate limiter plug at the same
time and the bucket is not yet initialized, both would try to initialize
the bucket resulting in an internal server error.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/plugs/rate_limiter/limiter_supervisor.ex | 10 | ||||
-rw-r--r-- | lib/pleroma/plugs/rate_limiter/rate_limiter.ex | 15 |
2 files changed, 18 insertions, 7 deletions
diff --git a/lib/pleroma/plugs/rate_limiter/limiter_supervisor.ex b/lib/pleroma/plugs/rate_limiter/limiter_supervisor.ex index 187582ede..884268d96 100644 --- a/lib/pleroma/plugs/rate_limiter/limiter_supervisor.ex +++ b/lib/pleroma/plugs/rate_limiter/limiter_supervisor.ex @@ -7,8 +7,8 @@ defmodule Pleroma.Plugs.RateLimiter.LimiterSupervisor do DynamicSupervisor.start_link(__MODULE__, init_arg, name: __MODULE__) end - def add_limiter(limiter_name, expiration) do - {:ok, _pid} = + def add_or_return_limiter(limiter_name, expiration) do + result = DynamicSupervisor.start_child( __MODULE__, %{ @@ -28,6 +28,12 @@ defmodule Pleroma.Plugs.RateLimiter.LimiterSupervisor do ]} } ) + + case result do + {:ok, _pid} = result -> result + {:error, {:already_started, pid}} -> {:ok, pid} + _ -> result + end end @impl true diff --git a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex index 9c362a392..b9cbe9716 100644 --- a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex +++ b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex @@ -171,7 +171,7 @@ defmodule Pleroma.Plugs.RateLimiter do {:error, value} {:error, :no_cache} -> - initialize_buckets(action_settings) + initialize_buckets!(action_settings) check_rate(action_settings) end end @@ -250,11 +250,16 @@ defmodule Pleroma.Plugs.RateLimiter do |> String.replace_leading(":", "") end - defp initialize_buckets(%{name: _name, limits: nil}), do: :ok + defp initialize_buckets!(%{name: _name, limits: nil}), do: :ok - defp initialize_buckets(%{name: name, limits: limits}) do - LimiterSupervisor.add_limiter(anon_bucket_name(name), get_scale(:anon, limits)) - LimiterSupervisor.add_limiter(user_bucket_name(name), get_scale(:user, limits)) + defp initialize_buckets!(%{name: name, limits: limits}) do + {:ok, _pid} = + LimiterSupervisor.add_or_return_limiter(anon_bucket_name(name), get_scale(:anon, limits)) + + {:ok, _pid} = + LimiterSupervisor.add_or_return_limiter(user_bucket_name(name), get_scale(:user, limits)) + + :ok end defp attach_identity(base, %{mode: :user, conn_info: conn_info}), |