Add relay-wide event ingest limiter
This commit is contained in:
@@ -5,6 +5,7 @@ defmodule Parrhesia.ApplicationTest do
|
||||
assert is_pid(Process.whereis(Parrhesia.Supervisor))
|
||||
assert is_pid(Process.whereis(Parrhesia.Telemetry))
|
||||
assert is_pid(Process.whereis(Parrhesia.Config))
|
||||
assert is_pid(Process.whereis(Parrhesia.Web.EventIngestLimiter))
|
||||
assert is_pid(Process.whereis(Parrhesia.Storage.Supervisor))
|
||||
assert is_pid(Process.whereis(Parrhesia.Subscriptions.Supervisor))
|
||||
assert is_pid(Process.whereis(Parrhesia.Auth.Supervisor))
|
||||
|
||||
@@ -8,6 +8,8 @@ defmodule Parrhesia.ConfigTest do
|
||||
assert Parrhesia.Config.get([:limits, :max_event_ingest_per_window]) == 120
|
||||
assert Parrhesia.Config.get([:limits, :max_tags_per_event]) == 256
|
||||
assert Parrhesia.Config.get([:limits, :max_tag_values_per_filter]) == 128
|
||||
assert Parrhesia.Config.get([:limits, :relay_max_event_ingest_per_window]) == 10_000
|
||||
assert Parrhesia.Config.get([:limits, :relay_event_ingest_window_seconds]) == 1
|
||||
assert Parrhesia.Config.get([:limits, :event_ingest_window_seconds]) == 1
|
||||
assert Parrhesia.Config.get([:limits, :auth_max_age_seconds]) == 600
|
||||
assert Parrhesia.Config.get([:limits, :max_outbound_queue]) == 256
|
||||
|
||||
@@ -424,6 +424,42 @@ defmodule Parrhesia.Web.ConnectionTest do
|
||||
]
|
||||
end
|
||||
|
||||
test "EVENT ingest enforces relay-wide rate limits" do
|
||||
limiter =
|
||||
start_supervised!(
|
||||
{Parrhesia.Web.EventIngestLimiter,
|
||||
name: nil, max_events_per_window: 1, window_seconds: 60}
|
||||
)
|
||||
|
||||
state =
|
||||
connection_state(
|
||||
event_ingest_limiter: limiter,
|
||||
max_event_ingest_per_window: 10,
|
||||
event_ingest_window_seconds: 60
|
||||
)
|
||||
|
||||
first_event = valid_event(%{"content" => "first"})
|
||||
second_event = valid_event(%{"content" => "second"})
|
||||
|
||||
assert {:push, {:text, first_response}, next_state} =
|
||||
Connection.handle_in({JSON.encode!(["EVENT", first_event]), [opcode: :text]}, state)
|
||||
|
||||
assert JSON.decode!(first_response) == ["OK", first_event["id"], true, "ok: event stored"]
|
||||
|
||||
assert {:push, {:text, second_response}, ^next_state} =
|
||||
Connection.handle_in(
|
||||
{JSON.encode!(["EVENT", second_event]), [opcode: :text]},
|
||||
next_state
|
||||
)
|
||||
|
||||
assert JSON.decode!(second_response) == [
|
||||
"OK",
|
||||
second_event["id"],
|
||||
false,
|
||||
"rate-limited: relay-wide EVENT ingress exceeded"
|
||||
]
|
||||
end
|
||||
|
||||
test "EVENT ingest enforces max event bytes" do
|
||||
state = connection_state(max_event_bytes: 128)
|
||||
|
||||
|
||||
16
test/parrhesia/web/event_ingest_limiter_test.exs
Normal file
16
test/parrhesia/web/event_ingest_limiter_test.exs
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule Parrhesia.Web.EventIngestLimiterTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Parrhesia.Web.EventIngestLimiter
|
||||
|
||||
test "allows events up to the configured relay-wide window cap" do
|
||||
limiter =
|
||||
start_supervised!(
|
||||
{EventIngestLimiter, name: nil, max_events_per_window: 2, window_seconds: 60}
|
||||
)
|
||||
|
||||
assert :ok = EventIngestLimiter.allow(limiter)
|
||||
assert :ok = EventIngestLimiter.allow(limiter)
|
||||
assert {:error, :relay_event_rate_limited} = EventIngestLimiter.allow(limiter)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user