-
Notifications
You must be signed in to change notification settings - Fork 69
/
entry.ex
111 lines (86 loc) · 2.3 KB
/
entry.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
defmodule Nebulex.Entry do
@moduledoc """
Defines a Cache Entry.
This is the structure used by the caches for representing cache entries.
"""
# Cache entry definition
defstruct key: nil,
value: nil,
touched: nil,
ttl: :infinity,
time_unit: :millisecond
@typedoc """
Defines a generic struct for a cache entry.
The entry depends on the adapter completely, this struct/type aims to define
the common fields.
"""
@type t :: %__MODULE__{
key: any,
value: any,
touched: integer,
ttl: timeout,
time_unit: System.time_unit()
}
alias Nebulex.Time
@doc """
Encodes a cache entry.
## Example
iex> "hello"
...> |> Nebulex.Entry.encode()
...> |> Nebulex.Entry.decode()
"hello"
"""
@spec encode(term, [term]) :: binary
def encode(data, opts \\ []) do
data
|> :erlang.term_to_binary(opts)
|> Base.encode64()
end
@doc """
Decodes a previously encoded entry.
## Example
iex> "hello"
...> |> Nebulex.Entry.encode()
...> |> Nebulex.Entry.decode()
"hello"
"""
# sobelow_skip ["Misc.BinToTerm"]
@spec decode(binary, [term]) :: term
def decode(data, opts \\ []) when is_binary(data) do
data
|> Base.decode64!()
|> :erlang.binary_to_term(opts)
end
@doc """
Returns whether the given `entry` has expired or not.
## Example
iex> Nebulex.Entry.expired?(%Nebulex.Entry{})
false
iex> Nebulex.Entry.expired?(
...> %Nebulex.Entry{touched: Nebulex.Time.now() - 10, ttl: 1}
...> )
true
"""
@spec expired?(t) :: boolean
def expired?(%__MODULE__{ttl: :infinity}), do: false
def expired?(%__MODULE__{touched: touched, ttl: ttl, time_unit: unit}) do
Time.now(unit) - touched >= ttl
end
@doc """
Returns the remaining time-to-live.
## Example
iex> Nebulex.Entry.ttl(%Nebulex.Entry{})
:infinity
iex> ttl =
...> Nebulex.Entry.ttl(
...> %Nebulex.Entry{touched: Nebulex.Time.now(), ttl: 100}
...> )
iex> ttl > 0
true
"""
@spec ttl(t) :: timeout
def ttl(%__MODULE__{ttl: :infinity}), do: :infinity
def ttl(%__MODULE__{ttl: ttl, touched: touched, time_unit: unit}) do
ttl - (Time.now(unit) - touched)
end
end