defmodule Kdb.Cache do
@table_name __MODULE__
@unit_time :millisecond
# @cleanup_interval :timer.minutes(15)
@expiration_time :timer.minutes(10)
@dev Mix.env() == :dev
def child_spec(_) do
%{
id: __MODULE__,
start: {__MODULE__, :init, []},
type: :worker,
restart: :permanent,
shutdown: 500
}
end
@doc """
Inicia el módulo de hits creando la tabla ETS.
"""
def init() do
# Crear tabla ETS con nombre del módulo, pública y con concurrencia de lectura
if :ets.whereis(@table_name) == :undefined do
:ets.new(@table_name, [
:set,
:public,
:named_table,
read_concurrency: true,
write_concurrency: true
])
end
:ignore
end
@spec put(atom() | String.t(), binary()) :: boolean()
def put(type, id) do
timestamp = now() + @expiration_time
:ets.insert(@table_name, {{id, type}, timestamp})
end
# @spec retrive_by_type(atom()) :: [binary() | String.t()]
# def retrive_by_type(type) do
# # :ets.fun2ms(fn {{id, 1}, _readed_at} -> id end)
# match_spec =
# [{{{:"$1", type}, :"$2"}, [], [:"$1"]}]
# :ets.select(@table_name, match_spec)
# end
@spec delete(atom(), binary()) :: true
def delete(type, id) do
:ets.delete(@table_name, {id, type})
end
defp now do
:os.system_time(@unit_time)
end
def cleanup(older_than) do
n =
:ets.foldl(
fn {key, readed_at}, acc ->
if readed_at < older_than do
:ets.delete(@table_name, key)
acc + 1
else
acc
end
end,
0,
@table_name
)
@dev and IO.puts("Deleted #{n} entries")
n
end
end