A simple http response caching system based on Plug and ETS. It easily integrates in every application that uses Plug, including a Phoenix dedicated adapter.
The main use case is when the contents of your web pages don't change in real time and are served to a multitude of visitors. Even if your server response times are in order of few tens of milliseconds, caching pages into ETS (hence into RAM) would shrink times to microseconds.
Cache duration can be configured with a combination of a ttl
value and ttl_check
. Check con_cache documentation for more details on this, PlugEtsCache uses it to read/write to ETS.
The package is available in Hex, follow these steps to install:
- Add
plug_ets_cache
to your list of dependencies inmix.exs
:
def deps do
# Get from hex
[{:plug_ets_cache, "~> 0.3.0"}]
# Or use the latest from master
[{:plug_ets_cache, github: "andreapavoni/plug_ets_cache"}]
end
- Ensure
plug_ets_cache
is started before your application:
def application do
[applications: [:plug_ets_cache]]
end
These are the common steps to setup PlugEtsCache
:
- Set configuration in
config/config.exs
(the following values are defaults):
config :plug_ets_cache,
db_name: :ets_cache,
ttl_check: 60,
ttl: 300
- Add
PlugEtsCache.Plug
to your router/plug:
plug PlugEtsCache.Plug
Now follow specific instructions below for your use case.
Because Phoenix has a more complex lifecycle when it comes to send a response, it has a special module for this.
- Add
use PlugEtsCache.Phoenix
- Call
cache_response
after you've sent a response:
defmodule MyApp.SomeController do
use MyApp.Web, :controller
use PlugEtsCache.Phoenix
# ...
def index(conn, _params) do
# ...
conn
|> render("index.html")
|> cache_response
end
# ...
end
Supposing a very simple Plug module:
- Import
PlugEtsCache.Response.cache_response/1
inside your module - Call
cache_response
after you've sent a response:
defmodule FooController do
use Plug.Router
import PlugEtsCache.Response, only: [cache_response: 1]
plug :match
plug :dispatch
get "/" do
Plug.Conn.fetch_query_params(conn)
|> put_resp_content_type("text/plain")
|> send_resp(200, "Hello cache")
|> cache_response
end
end
cache_response/1
will adhere to the ttl
value in the config, but
you can instead use cache_response/2
to specify a custom ttl
for each
response. Examples:
cache_response(conn, :timer.hours(1))
cache_response(conn, ttl: :timer.minutes(45))
If you need greater control over the key used to cache the request you can use a custom function to build the cache key.
The function needs to accept one argument, the Plug.Conn
struct, and return the key.
cache_response(conn, [cache_key: fn conn -> conn.request_path end, ttl: :timer.minutes(10)])
The docs can be found at https://hexdocs.pm/plug_ets_cache.
- add more detailed docs
Everyone is welcome to contribute to PlugEtsCache and help tackling existing issues!
Use the issue tracker for bug reports or feature requests.
Please, do your best to follow the Elixir's Code of Conduct.
This source code is released under MIT License. Check LICENSE file for more information.