basic admin endgame view and add
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
defmodule Chesstrainer.Cache do
|
||||
@moduledoc """
|
||||
Generic LRU cache.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> start_link(:tablebase)
|
||||
"""
|
||||
|
||||
use GenServer
|
||||
|
||||
@max_size 1000
|
||||
@backup_interval_minutes 60
|
||||
|
||||
def start_link(table), do: GenServer.start_link(__MODULE__, table, name: via_tuple(table))
|
||||
def put(table, key, value), do: GenServer.call(via_tuple(table), {:put, key, value})
|
||||
def get(table, key), do: GenServer.call(via_tuple(table), {:get, key})
|
||||
def delete(table, key), do: GenServer.call(via_tuple(table), {:delete, key})
|
||||
def backup(table), do: GenServer.cast(via_tuple(table), :backup)
|
||||
|
||||
def show(table) do
|
||||
ensure_table(table)
|
||||
:ets.tab2list(table)
|
||||
end
|
||||
|
||||
def size(table), do: :ets.info(table, :size)
|
||||
|
||||
@impl true
|
||||
def init(table) do
|
||||
{:ok, table, {:continue, :restore_and_backup}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_continue(:restore_and_backup, table) do
|
||||
create_table(table)
|
||||
__MODULE__.Persist.restore(table)
|
||||
:timer.send_interval(:timer.minutes(@backup_interval_minutes), :backup)
|
||||
{:noreply, table}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call({:put, key, value}, _from, table) do
|
||||
ensure_table(table)
|
||||
timestamp = System.system_time(:millisecond)
|
||||
:ets.insert(table, {key, value, timestamp})
|
||||
|
||||
GenServer.cast(self(), :maybe_evict)
|
||||
|
||||
{:reply, :ok, table}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call({:get, key}, _from, table) do
|
||||
ensure_table(table)
|
||||
|
||||
case :ets.lookup(table, key) do
|
||||
[{^key, value, _old_timestamp}] ->
|
||||
timestamp = System.system_time(:millisecond)
|
||||
:ets.insert(table, {key, value, timestamp})
|
||||
{:reply, {:ok, value}, table}
|
||||
|
||||
[] ->
|
||||
{:reply, :error, table}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call({:delete, key}, _from, table) do
|
||||
:ets.delete(table, key)
|
||||
{:reply, :ok, table}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast(:maybe_evict, table) do
|
||||
__MODULE__.Evict.maybe_evict_oldest(table, @max_size)
|
||||
{:noreply, table}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast(:backup, table) do
|
||||
__MODULE__.Persist.backup(table)
|
||||
{:noreply, table}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:backup, table) do
|
||||
GenServer.cast(self(), :backup)
|
||||
{:noreply, table}
|
||||
end
|
||||
|
||||
defp via_tuple(table), do: {:via, Registry, {Chesstrainer.CacheRegistry, table}}
|
||||
|
||||
defp ensure_table(table) do
|
||||
case :ets.whereis(table) do
|
||||
:undefined -> create_table(table)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp create_table(table), do: :ets.new(table, [:named_table, :public, :set])
|
||||
end
|
||||
Reference in New Issue
Block a user