Current section
2 Versions
Jump to
Current section
2 Versions
Compare versions
6
files changed
+85
additions
-18
deletions
| @@ -1,5 +1,15 @@ | |
| 1 1 | # Changelog |
| 2 2 | |
| 3 | + ## v0.2.0 (2016-03-27) |
| 4 | + |
| 5 | + - Enhancements |
| 6 | + - Agent caches can auto expire keys after configurable seconds |
| 7 | + - ETS caches can auto expire keys after configurable seconds |
| 8 | + |
| 9 | + - Backwards incompatible changes |
| 10 | + - Minimum required elixir version is now "~> 1.2" |
| 11 | + - Minimum required erlang version is now "~> 18.0" |
| 12 | + |
| 3 13 | ## v0.1.0 (2016-03-13) |
| 4 14 | |
| 5 15 | - Initial Release |
| @@ -23,7 +23,7 @@ Add the plug as a dependency to your `mix.exs` file: | |
| 23 23 | |
| 24 24 | ```elixir |
| 25 25 | defp deps do |
| 26 | - [ { :plug_pagecache, "~> 0.1" } ] |
| 26 | + [ { :plug_pagecache, "~> 0.2" } ] |
| 27 27 | end |
| 28 28 | ``` |
| 29 29 | |
| @@ -48,11 +48,13 @@ use Mix.Config | |
| 48 48 | config :plug_pagecache, |
| 49 49 | :caches, |
| 50 50 | my_agent_cache: [ |
| 51 | - adapter: Plug.PageCache.Adapter.Agent |
| 51 | + adapter: Plug.PageCache.Adapter.Agent, |
| 52 | + auto_expire: 3600 |
| 52 53 | ], |
| 53 54 | my_ets_cache: [ |
| 54 | - adapter: Plug.PageCache.Adapter.ETS, |
| 55 | - table: :my_ets_table |
| 55 | + adapter: Plug.PageCache.Adapter.ETS, |
| 56 | + auto_expire: 3600, |
| 57 | + table: :my_ets_table |
| 56 58 | ] |
| 57 59 | ``` |
| 58 60 | |
| @@ -113,6 +115,8 @@ Uses a plain `GenServer` to serve responses directly from memory (== state). | |
| 113 115 | |
| 114 116 | Requires no additional configuration. |
| 115 117 | |
| 118 | + Optionally takes an `:auto_expire` value as entry lifetime in seconds. |
| 119 | + |
| 116 120 | ### Plug.PageCache.Adapter.ETS |
| 117 121 | |
| 118 122 | Uses an `ets table` to serve reseponses. |
| @@ -120,6 +124,8 @@ Uses an `ets table` to serve reseponses. | |
| 120 124 | Responses are stored in a `:named_table` you have to configure |
| 121 125 | using the `:table` key. |
| 122 126 | |
| 127 | + Optionally takes an `:auto_expire` value as entry lifetime in seconds. |
| 128 | + |
| 123 129 | |
| 124 130 | ## License |
| @@ -1,7 +1,7 @@ | |
| 1 1 | {<<"app">>,<<"plug_pagecache">>}. |
| 2 2 | {<<"build_tools">>,[<<"mix">>]}. |
| 3 3 | {<<"description">>,<<"Plug for full page response caching">>}. |
| 4 | - {<<"elixir">>,<<"~> 1.0">>}. |
| 4 | + {<<"elixir">>,<<"~> 1.2">>}. |
| 5 5 | {<<"files">>, |
| 6 6 | [<<"CHANGELOG.md">>,<<"mix.exs">>,<<"README.md">>, |
| 7 7 | <<"lib/plug/pagecache.ex">>,<<"lib/plug/pagecache/adapter.ex">>, |
| @@ -22,4 +22,4 @@ | |
| 22 22 | [{<<"app">>,<<"plug">>}, |
| 23 23 | {<<"optional">>,true}, |
| 24 24 | {<<"requirement">>,<<"~> 1.0">>}]}]}. |
| 25 | - {<<"version">>,<<"0.1.0">>}. |
| 25 | + {<<"version">>,<<"0.2.0">>}. |
| @@ -5,10 +5,49 @@ defmodule Plug.PageCache.Adapter.Agent do | |
| 5 5 | |
| 6 6 | use Plug.PageCache.Adapter |
| 7 7 | |
| 8 | - def init(_opts), do: { :ok, %{} } |
| 9 8 | |
| 10 | - def clean(_state), do: { %{}, :ok } |
| 11 | - def load(state, path), do: { state, Map.get(state, path, nil) } |
| 12 | - def remove(state, path), do: { Map.delete(state, path), :ok } |
| 13 | - def save(state, path, page), do: { Map.put(state, path, page), :ok } |
| 9 | + # Adapter lifecycle |
| 10 | + |
| 11 | + def init(opts) do |
| 12 | + { :ok, %{ auto_expire: opts[:auto_expire] || 0, |
| 13 | + entries: %{} }} |
| 14 | + end |
| 15 | + |
| 16 | + |
| 17 | + # Adapter methods |
| 18 | + |
| 19 | + def clean(state) do |
| 20 | + { %{ state | entries: %{} }, :ok } |
| 21 | + end |
| 22 | + |
| 23 | + def load(state, path) do |
| 24 | + { state, load_unexpired(path, state) } |
| 25 | + end |
| 26 | + |
| 27 | + def remove(state, path) do |
| 28 | + { %{ state | entries: Map.delete(state.entries, path) }, :ok } |
| 29 | + end |
| 30 | + |
| 31 | + def save(state, path, page) do |
| 32 | + entry = { page, :os.system_time(:seconds) + state.auto_expire } |
| 33 | + |
| 34 | + { %{ state | entries: Map.put(state.entries, path, entry) }, :ok } |
| 35 | + end |
| 36 | + |
| 37 | + |
| 38 | + # Internal methods |
| 39 | + |
| 40 | + defp load_unexpired(path, %{ auto_expire: 0 } = state) do |
| 41 | + { page, _ } = Map.get(state.entries, path, { nil, 0 }) |
| 42 | + page |
| 43 | + end |
| 44 | + |
| 45 | + defp load_unexpired(path, state) do |
| 46 | + { page, expire_after } = Map.get(state.entries, path, { nil, 0 }) |
| 47 | + |
| 48 | + case :os.system_time(:seconds) <= expire_after do |
| 49 | + true -> page |
| 50 | + false -> nil |
| 51 | + end |
| 52 | + end |
| 14 53 | end |
| @@ -7,6 +7,9 @@ defmodule Plug.PageCache.Adapter.ETS do | |
| 7 7 | |
| 8 8 | require Logger |
| 9 9 | |
| 10 | + |
| 11 | + # Adapter lifecycle |
| 12 | + |
| 10 13 | def init(opts) do |
| 11 14 | ets_tid = case opts[:table] do |
| 12 15 | nil -> |
| @@ -17,10 +20,13 @@ defmodule Plug.PageCache.Adapter.ETS do | |
| 17 20 | table -> :ets.new(table, [ :protected, :named_table, :set ]) |
| 18 21 | end |
| 19 22 | |
| 20 | - { :ok, %{ ets_tid: ets_tid }} |
| 23 | + { :ok, %{ auto_expire: opts[:auto_expire] || 0, |
| 24 | + ets_tid: ets_tid }} |
| 21 25 | end |
| 22 26 | |
| 23 27 | |
| 28 | + # Adapter methods |
| 29 | + |
| 24 30 | def clean(state) do |
| 25 31 | _ = :ets.delete_all_objects(state.ets_tid) |
| 26 32 | |
| @@ -29,8 +35,13 @@ defmodule Plug.PageCache.Adapter.ETS do | |
| 29 35 | |
| 30 36 | def load(state, path) do |
| 31 37 | case :ets.lookup(state.ets_tid, path) do |
| 32 | - [{ ^path, page }] -> { state, page } |
| 33 | - _ -> { state, nil } |
| 38 | + [{ ^path, page, expire_after }] -> |
| 39 | + case :os.system_time(:seconds) <= expire_after do |
| 40 | + true -> { state, page } |
| 41 | + false -> { state, nil } |
| 42 | + end |
| 43 | + |
| 44 | + _ -> { state, nil } |
| 34 45 | end |
| 35 46 | end |
| 36 47 | |
| @@ -41,7 +52,8 @@ defmodule Plug.PageCache.Adapter.ETS do | |
| 41 52 | end |
| 42 53 | |
| 43 54 | def save(state, path, page) do |
| 44 | - _ = :ets.insert(state.ets_tid, { path, page }) |
| 55 | + expire_after = :os.system_time(:seconds) + state.auto_expire |
| 56 | + _ = :ets.insert(state.ets_tid, { path, page, expire_after }) |
| 45 57 | |
| 46 58 | { state, :ok } |
| 47 59 | end |
Loading more files…