An implementation with ets.
Let’s start with implementation
defmodule SimpleCache do @table :simple_cache def init(_) do :ets.new(@table, [ :set, :named_table, :public, read_concurrency: true, write_concurrency: true ]) {:ok, %{}} end def start_link do GenServer.start_link(__MODULE__, [], name: __MODULE__) end def fetch(key, expires_in_seconds, fun) do case lookup(key) do {:hit, value} -> value :miss -> value = fun.() put(key, expires_in_seconds, value) value end end defp lookup(key) do case :ets.lookup(@table, key) do [{^key, expires_at, value}] -> case now < expires_at do true -> {:hit, value} false -> :miss end _ -> :miss end end defp put(key, expires_in_seconds, value) do expires_at = now + expires_in_seconds :ets.insert(@table, {key, expires_at, value}) end defp now do :erlang.system_time(:seconds) end end
Update application.ex
def start(_type, _args) do import Supervisor.Spec children = [ supervisor(SimpleCache, []) ] opts = [strategy: :one_for_one, name: Supervisor] Supervisor.start_link(children, opts) end
Finally, use it
cache_for_seconds = 60 key = 'key' SimpleCache.fetch(key, cache_for_seconds, fn -> {:ok, some_expensive_operation} end)
Relavent links:
https://stackoverflow.com/questions/35218738/caching-expensive-computation-in-elixir
https://dockyard.com/blog/2017/05/19/optimizing-elixir-and-phoenix-with-ets