-
Notifications
You must be signed in to change notification settings - Fork 10
/
cache.ex
74 lines (61 loc) · 1.72 KB
/
cache.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
defmodule ATECC508A.Transport.Cache do
@moduledoc """
Simple cache for reducing unnecessary traffic to the ATECC508A
"""
use GenServer
@atecc508a_op_read 0x02
@atecc508a_op_genkey 0x40
@atecc508a_op_random 0x1B
@spec start_link() :: GenServer.on_start()
def start_link do
GenServer.start_link(__MODULE__, nil)
end
@doc """
Check if the specified request is in the cache
"""
@spec get(GenServer.server(), binary()) :: binary() | nil
def get(pid, request) do
GenServer.call(pid, {:get, request})
end
@doc """
Save a response back to the cache
"""
@spec put(GenServer.server(), binary(), any()) :: any()
# Cache all reads
def put(pid, <<@atecc508a_op_read, _::binary>> = request, response) do
GenServer.call(pid, {:put, request, response})
end
# Cache the response to getting a public key
def put(pid, <<@atecc508a_op_genkey, 0, _key_id::little-16>> = request, response) do
GenServer.call(pid, {:put, request, response})
end
# Don't cache random numbers
def put(_pid, <<@atecc508a_op_random, _::binary>>, response), do: response
# Flush the cache on everything else:
# writes, locks, etc.
#
# This is overkill, but safe.
def put(pid, _request, response) do
GenServer.call(pid, :flush)
response
end
@impl true
def init(_) do
cache = %{}
{:ok, cache}
end
@impl true
def handle_call({:get, request}, _from, cache) do
result = Map.get(cache, request)
{:reply, result, cache}
end
@impl true
def handle_call({:put, request, response}, _from, cache) do
new_cache = Map.put(cache, request, response)
{:reply, response, new_cache}
end
@impl true
def handle_call(:flush, _from, _cache) do
{:reply, :ok, %{}}
end
end