Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
## v0.1.2 (2024-12-30)

### Implements Reset function

- `GenCache.reset(pid)`
- or macro-based module: `SomeCache.reset()`


## v0.1.1 (2024-09-09)


### Quality of life improvements

- allow configuring default ttl when starting the server
Expand All @@ -11,4 +20,4 @@

### First release

- already quite usable, there might still be some missing features
- already quite usable, there might still be some missing features
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ res = MyCache.request({IO, :puts, ["Hello World"]})
# this will not execute the MFA tuple and just return the cached result
res = MyCache.request({IO, :puts, ["Hello World"]})

# remove a single entry from cache
MyCache.remove({IO, :puts, ["Hello World"]})

# Reset the complete cache
MyCache.reset()

# add custom ttl for the given key
res = MyCache.request({IO, :puts, ["Quick one"]}, ttl: :timer.seconds(5))
Expand Down Expand Up @@ -59,4 +64,3 @@ end
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/gen_cache>.

10 changes: 10 additions & 0 deletions lib/gen_cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ defmodule GenCache do
def request(pid, request, opts \\ []), do: :gen_statem.call(pid, {:request, request, opts})
def remove(pid, request), do: :gen_statem.call(pid, {:remove, request})
def get_state(pid), do: :gen_statem.call(pid, :get_state)
def reset(pid), do: :gen_statem.call(pid, :reset)

### INTERNAL ###

Expand All @@ -87,6 +88,11 @@ defmodule GenCache do
{:keep_state, data, [{:reply, from, :ok}]}
end

def handle_event({:call, from}, :reset, _state, data) do
data = reset_cache(data)
{:keep_state, data, [{:reply, from, :ok}]}
end

#
def handle_event({:call, from}, {:request, request, req_opts}, _, data) do
ttl = Keyword.get(req_opts, :ttl, @default_ttl)
Expand Down Expand Up @@ -184,6 +190,10 @@ defmodule GenCache do
%Data{data | cache: Map.delete(data.cache, request)}
end

def reset_cache(data) do
%Data{data | cache: %{}, valid_until: %{}, ttl: %{}}
end

defp get_from_cache(data, request) do
res = Map.get(data.cache, request, nil)

Expand Down
1 change: 1 addition & 0 deletions lib/gen_cache/macro.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ defmodule GenCache.Macro do

def remove(request), do: :gen_statem.call(__MODULE__, {:remove, request})
def get_state(), do: :gen_statem.call(__MODULE__, :get_state)
def reset(), do: :gen_statem.call(__MODULE__, :reset)

### INTERNAL ###

Expand Down
13 changes: 13 additions & 0 deletions lib/gen_cache/macro_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,17 @@ defmodule GenCache.MacroTest do
{:ok, pid} = TestCache.start_link()
assert {:error, {:already_started, pid}} == TestCache.start_link()
end

test "reset works" do
TestCache.start_link()
TestCache.request({Process, :send, [self(), :start, []]})
TestCache.request({Process, :send, [self(), :start, []]})
assert_received :start
refute_received :start

## RESET clears the cache, so the next request MUST be executed
TestCache.reset()
TestCache.request({Process, :send, [self(), :start, []]})
assert_received :start
end
end
36 changes: 36 additions & 0 deletions lib/gen_cache_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,42 @@ defmodule GenCacheTest do
end
end

describe "reset" do
test "resets cache" do
{:ok, pid} = GenCache.start_link([])
GenCache.request(pid, req_tuple(1))
GenCache.request(pid, req_tuple(2))
res = clean_state(pid)

assert res == %GenCache.Data{
ttl: %{
{GenCacheTest.ReqBackend, :fetch, [1]} => 30000,
{GenCacheTest.ReqBackend, :fetch, [2]} => 30000
},
busy: %{},
cache: %{
{GenCacheTest.ReqBackend, :fetch, [1]} => "RESULT: 1",
{GenCacheTest.ReqBackend, :fetch, [2]} => "RESULT: 2"
},
valid_until: %{},
purge_loop: 5000,
default_ttl: 30000
}

GenCache.reset(pid)
res = clean_state(pid)

assert res == %GenCache.Data{
ttl: %{},
busy: %{},
cache: %{},
valid_until: %{},
purge_loop: 5000,
default_ttl: 30000
}
end
end

describe "raising response" do
test "is not cached" do
defmodule RaisingBackend do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule GenCache.MixProject do
use Mix.Project

@github_url "https://github.com/maxohq/gen_cache"
@version "0.1.1"
@version "0.1.2"
@description "gen_statem based generic cache with MFA-based keys"

def project do
Expand Down