Leon4gr45's picture
Upload folder using huggingface_hub
384f6a2 verified
Raw
History Blame Contribute Delete
2.22 kB
defmodule Plausible.Session.Salts do
use GenServer
use Plausible.Repo
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: opts[:name] || __MODULE__)
end
@impl true
def init(opts) do
name = opts[:name] || __MODULE__
now = opts[:now] || DateTime.utc_now()
clean_old_salts(now)
^name =
:ets.new(name, [
:named_table,
:set,
:protected,
{:read_concurrency, true}
])
refresh(name, now)
{:ok, name}
end
def refresh(name, now) do
salts = try do
Repo.all(from s in "salts", select: s.salt, order_by: [desc: s.id], limit: 2)
rescue
_ -> []
end
state =
case salts do
[current, prev] ->
%{previous: prev, current: current}
[current] ->
%{previous: nil, current: current}
[] ->
new = generate_and_persist_new_salt(now)
%{previous: nil, current: new}
end
true = :ets.insert(name, {:state, state})
interval = Application.get_env(:plausible, __MODULE__)[:interval] || :timer.seconds(90)
Process.send_after(self(), {:refresh, now}, interval)
:ok
end
def rotate(name \\ __MODULE__, now \\ DateTime.utc_now()) do
GenServer.call(name, {:rotate, now})
end
def fetch(name \\ __MODULE__) do
[state: state] = :ets.lookup(name, :state)
state
end
@impl true
def handle_call({:rotate, now}, _from, name) do
current = fetch(name).current
clean_old_salts(now)
state =
%{
current: generate_and_persist_new_salt(now),
previous: current
}
true = :ets.insert(name, {:state, state})
{:reply, :ok, name}
end
@impl true
def handle_info({:refresh, now}, name) do
refresh(name, now)
{:noreply, name}
end
defp generate_and_persist_new_salt(now) do
salt = :crypto.strong_rand_bytes(16)
try do
Repo.insert_all("salts", [%{salt: salt, inserted_at: now}])
rescue
_ -> :ok
end
salt
end
defp clean_old_salts(now) do
h48_ago =
DateTime.shift(now, hour: -48)
try do
Repo.delete_all(from s in "salts", where: s.inserted_at < ^h48_ago)
rescue
_ -> :ok
end
end
end