forked from AkkomaGang/akkoma
4d416343fa
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.
50 lines
1.1 KiB
Elixir
50 lines
1.1 KiB
Elixir
defmodule Pleroma.Plugs.RateLimiter.LimiterSupervisor do
|
|
use DynamicSupervisor
|
|
|
|
import Cachex.Spec
|
|
|
|
def start_link(init_arg) do
|
|
DynamicSupervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
|
|
end
|
|
|
|
def add_or_return_limiter(limiter_name, expiration) do
|
|
result =
|
|
DynamicSupervisor.start_child(
|
|
__MODULE__,
|
|
%{
|
|
id: String.to_atom("rl_#{limiter_name}"),
|
|
start:
|
|
{Cachex, :start_link,
|
|
[
|
|
limiter_name,
|
|
[
|
|
expiration:
|
|
expiration(
|
|
default: expiration,
|
|
interval: check_interval(expiration),
|
|
lazy: true
|
|
)
|
|
]
|
|
]}
|
|
}
|
|
)
|
|
|
|
case result do
|
|
{:ok, _pid} = result -> result
|
|
{:error, {:already_started, pid}} -> {:ok, pid}
|
|
_ -> result
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def init(_init_arg) do
|
|
DynamicSupervisor.init(strategy: :one_for_one)
|
|
end
|
|
|
|
defp check_interval(exp) do
|
|
(exp / 2)
|
|
|> Kernel.trunc()
|
|
|> Kernel.min(5000)
|
|
|> Kernel.max(1)
|
|
end
|
|
end
|