mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-11 16:08:09 +00:00
40 lines
1.1 KiB
Elixir
40 lines
1.1 KiB
Elixir
defmodule Realtime.Test.Counter do
|
|
@moduledoc """
|
|
In-memory stand-in for the Redis counter behind `Realtime.RateLimiter`.
|
|
|
|
Selected via `config :realtime, rate_limit_counter:` so the suite exercises
|
|
real limiter decisions without a live Redis. `simulate_outage/1` returns nil
|
|
the way `Realtime.Redis.incr_with_ttl/2` does when Redis is unreachable, which
|
|
is what the limiter's fail-open path keys on.
|
|
"""
|
|
|
|
use Agent
|
|
|
|
def start_link(_opts \\ []) do
|
|
Agent.start_link(fn -> %{counts: %{}, down: false} end, name: __MODULE__)
|
|
end
|
|
|
|
def reset do
|
|
Agent.update(__MODULE__, fn _ -> %{counts: %{}, down: false} end)
|
|
end
|
|
|
|
def simulate_outage(down?) do
|
|
Agent.update(__MODULE__, &Map.put(&1, :down, down?))
|
|
end
|
|
|
|
def count(key) do
|
|
Agent.get(__MODULE__, &get_in(&1, [:counts, key])) || 0
|
|
end
|
|
|
|
def incr_with_ttl(key, _ttl_seconds) do
|
|
Agent.get_and_update(__MODULE__, fn
|
|
%{down: true} = state ->
|
|
{nil, state}
|
|
|
|
%{counts: counts} = state ->
|
|
next = Map.get(counts, key, 0) + 1
|
|
{next, %{state | counts: Map.put(counts, key, next)}}
|
|
end)
|
|
end
|
|
end
|