Current section
Files
Jump to
Current section
Files
lib/plug_cache.ex
defmodule PlugCache do
import Plug.Conn, only: [register_before_send: 2, send_resp: 3, halt: 1]
alias PlugCache.Cache
def init(opts \\ []), do: opts
def call(conn, opts) do
if Cache.has_key?(key(conn)) do
send_resp_with_cache(conn, opts)
else
conn
|> register_before_send(&set_cache(&1, opts))
end
end
defp key(%Plug.Conn{params: %Plug.Conn.Unfetched{}} = conn) do
%{request_path: request_path, query_string: query_string} = conn
"#{request_path}#{query_string}"
end
defp key(%Plug.Conn{request_path: request_path, params: params} = _conn) do
"#{request_path}#{Plug.Conn.Query.encode(params)}"
end
defp send_resp_with_cache(conn, opts) do
case Cache.get(key(conn), opts) do
nil ->
conn
body ->
conn
|> send_resp(:ok, body)
|> halt
end
end
defp set_cache(%Plug.Conn{resp_body: body} = conn, opts) do
Cache.set(key(conn), body, opts)
conn
end
def invalidate(prefix) do
with keys <- Cache.keys(),
filtered_keys <- Enum.filter(keys, &filter_by_path(&1, prefix)) do
Task.async_stream(filtered_keys, __MODULE__, :invalidate_key, [])
|> Enum.to_list()
end
end
defp filter_by_path(key, path), do: String.starts_with?(key, path)
def invalidate_key(key) do
Cache.delete(key)
end
end