nebulex v1.0.0-rc.2 Nebulex.Cache behaviour View Source
Cache Main Interface.
A Cache maps to an underlying implementation, controlled by the adapter. For example, Nebulex ships with a default adapter that implements a local generational cache.
When used, the Cache expects the :otp_app
as option.
The :otp_app
should point to an OTP application that has
the Cache configuration. For example, the Cache:
defmodule MyCache do
use Nebulex.Cache, otp_app: :my_app
end
Could be configured with:
config :my_app, MyCache,
adapter: Nebulex.Adapters.Local,
n_shards: 2
Most of the configuration that goes into the config
is specific
to the adapter, so check Nebulex.Adapters.Local
documentation
for more information. However, some configuration is shared across
all adapters, they are:
:adapter
- a compile-time option that specifies the adapter itself. As a compile-time option, it may also be given as an option touse Nebulex.Cache
.:stats
- a compile-time option that specifies if cache statistics is enabled or not (defaults tofalse
).:pre_hooks_strategy
- a compile-time option that determinates the strategy how pre-hooks will be executed – see pre/post hooks below.:post_hooks_strategy
- a compile-time option that determinates the strategy how post-hooks will be executed – see pre/post hooks below.:version_generator
- this option specifies the module that implements theNebulex.Version
interface. This interface defines only one callbackgenerate/1
that is invoked by the adapters to generate new object versions. If this option is not set, then the version is set tonil
by default.
Pre/Post hooks
The cache can also provide its own pre/post hooks implementation; see
Nebulex.Cache.Hook
behaviour. By default, pre/post hooks are empty lists,
but again, you can override the functions of Nebulex.Cache.Hook
behaviour.
Besides, it is possible to configure the strategy how the hooks are evaluated, the available strategies are:
:async
- (the default) all hooks are evaluated asynchronously (in parallel) and their results are ignored.:sync
- hooks are evaluated synchronously (sequentially) and their results are ignored.:pipe
- similar to:sync
but each hook result is passed to the next one and so on, until the last hook evaluation is returned.
These strategy values applies to the compile-time options
:pre_hooks_strategy
and :post_hooks_strategy
.
Shared options
Almost all of the Cache operations below accept the following options:
:return
- selects return type. When:value
(the default), returns the objectvalue
. When:object
, returns theNebulex.Object.t
.:version
- The version of the object on which the operation will take place. The version can be any term (default:nil
).:ttl
- Time To Live (TTL) or expiration time in milliseconds for a key (default::infinity
) – applies only toset/3
.
Such cases will be explicitly documented as well as any extra option.
Extended API
Some adapters might extend the API with additional functions, therefore, it is important to review the adapters documentation.
Link to this section Summary
Callbacks
Returns the adapter tied to the cache
Returns the adapter configuration stored in the :otp_app
environment
Deletes the cached entry in for a specific key
Flushes the cache
Fetches a value or object from Cache where the key matches the
given key
Similar to get/2
but raises KeyError
if no value associated with the
given key
was found
Gets the value from key
and updates it, all in one pass
Returns whether the given key
exists in Cache
Returns true
if the current process is inside a transaction
A callback executed when the cache starts or when configuration is read
Returns all cached keys
Returns and removes the value/object associated with key
in Cache
Invokes reducer
for each entry in the cache, passing the key, the return
and the accumulator acc
as arguments. reducer
’s return value is stored
in acc
Sets the given value
under key
in the Cache
Returns the cache size (total number of cached entries)
Starts a supervision and return {:ok, pid}
or just :ok
if nothing
needs to be done
Shuts down the cache represented by the given pid
Returns a map with all cache entries (key/value). If you want the map values
be the cache object, pass the option :return
set to :object
Runs the given function inside a transaction
Updates the cached key
with the given function
Updates (increment or decrement) the counter mapped to the given key
Link to this section Types
Link to this section Callbacks
Returns the adapter tied to the cache.
Returns the adapter configuration stored in the :otp_app
environment.
If the c:init/2
callback is implemented in the cache, it will be invoked.
Deletes the cached entry in for a specific key
.
It always returns the key
, either it exists or not. It the key
exists,
it’s removed from cache, otherwise nothing happens.
Options
:on_conflict
- It may be one of:raise
(the default),:nothing
,:delete
. See the “OnConflict” section for more information.
Note that for this function :return
option hasn’t any effect
since it always returns the key
either success or not.
See the “Shared options” section at the module documentation.
Example
nil =
:a
|> MyCache.set(1, return: :key)
|> MyCache.delete()
|> MyCache.get()
:non_existent_key = MyCache.delete :non_existent_key
OnConflict
The :on_conflict
option supports the following values:
:raise
- raises if there is a conflicting key:nothing
- ignores the error in case of conflicts:delete
- deletes the value on the existing key
Examples
# Set a value
1 = MyCache.set :a, 1
# Delete with an invalid version but do nothing on conflicts.
# Keep in mind that, although this returns successfully, the returned
# `kwy` does not reflect the data in the Cache. For instance, in case
# of "on_conflict: :nothing", the returned `key` isn't deleted.
:a = MyCache.delete :a, version: :invalid, on_conflict: :nothing
1 = MyCache.get :a
# Delete with the same invalid version but force to delete the current
# value on conflicts (if it exist).
:a = MyCache.delete :a, version: :invalid, on_conflict: :delete
nil = MyCache.get :a
Flushes the cache.
Examples
for x <- 1..5, do: MyCache.set(x, x)
:ok = MyCache.flush
for x <- 1..5, do: nil = MyCache.get(x)
Fetches a value or object from Cache where the key matches the
given key
.
Returns nil
if no result was found.
Options
:on_conflict
- It may be one of:raise
(the default),:nothing
,nil
. See the “OnConflict” section for more information.
See the “Shared options” section at the module documentation.
Example
"some value" =
:a
|> MyCache.set("some value", return: :key)
|> MyCache.get
nil = MyCache.get :non_existent_key
OnConflict
The :on_conflict
option supports the following values:
:raise
- raises if there is a conflicting key:nothing
- ignores the error in case of conflictsnil
- forces to returnnil
Examples
# Set a value
1 = MyCache.set :a, 1
# Gets with an invalid version but do nothing on conflicts.
# Keep in mind that, although this returns successfully, the returned
# struct does not reflect the data in the Cache. For instance, in case
# of "on_conflict: :nothing", it returns the latest version of the
# cached object.
%Nebulex.Object{key: :a, value: 1} =
MyCache.get :a, return: :object, version: :invalid, on_conflict: :nothing
1 = MyCache.get :a
# Gets with the same invalid version but force to return `nil`
nil = MyCache.get :a, version: :invalid, on_conflict: nil
1 = MyCache.get :a
Similar to get/2
but raises KeyError
if no value associated with the
given key
was found.
Options
See the “Shared options” section at the module documentation.
Example
MyCache.get!(:a)
Gets the value from key
and updates it, all in one pass.
fun
is called with the current cached value under key
(or nil
if key
hasn’t been cached) and must return a two-element tuple:
the “get” value (the retrieved value, which can be operated on before
being returned) and the new value to be stored under key
. fun
may
also return :pop
, which means the current value shall be removed
from Cache and returned.
The returned value is a tuple with the “get” value returned by
fun
and the new updated value under key
.
Options
:on_conflict
- same as callbackget/2
.
Note that for this function :return
option hasn’t any effect,
since it always returns a tuple {get :: value, update :: value}
in case of success.
See the “Shared options” section at the module documentation.
Examples
# update a nonexistent key
{nil, "value!"} = MyCache.get_and_update(:a, fn current_value ->
{current_value, "value!"}
end)
# update a existent key
{"value!", "new value!"} = MyCache.get_and_update(:a, fn current_value ->
{current_value, "new value!"}
end)
# pop/remove value if it exists
{"new value!", nil} = MyCache.get_and_update(:a, fn _ -> :pop end)
# pop/remove a nonexistent key
{nil, nil} = MyCache.get_and_update(:b, fn _ -> :pop end)
Returns whether the given key
exists in Cache.
Examples
1 = MyCache.set(:a, 1)
true = MyCache.has_key?(:a)
false = MyCache.has_key?(:b)
Returns true
if the current process is inside a transaction.
Examples
MyCache.in_transaction?
#=> false
MyCache.transaction(fn ->
MyCache.in_transaction? #=> true
end)
A callback executed when the cache starts or when configuration is read.
Returns all cached keys.
Examples
for x <- 1..3, do: MyCache.set(x, x*2, return: :key)
[1, 2, 3] = MyCache.keys
WARNING: This is an expensive operation, beware of using it in prod.
Returns and removes the value/object associated with key
in Cache.
Returns nil
if no result was found.
Options
:on_conflict
- same as callbackget/2
.
See the “Shared options” section at the module documentation.
Examples
1 = MyCache.set(:a, 1)
1 = MyCache.pop(:a)
nil = MyCache.pop(:b)
%Nebulex.Object{key: :a, value: 1} =
:a |> MyCache.set(1, return: :key) |> MyCache.pop(return: :object)
Invokes reducer
for each entry in the cache, passing the key, the return
and the accumulator acc
as arguments. reducer
’s return value is stored
in acc
.
Returns the accumulator.
Options
See the “Shared options” section at the module documentation.
Examples
for x <- 1..5, do: MyCache.set(x, x)
15 = MyCache.reduce(0, fn({_key, value}, acc) ->
acc + value
end)
MyCache.reduce({%{}, 0}, fn({key, value}, {acc1, acc2}) ->
if Map.has_key?(acc1, key),
do: {acc1, acc2},
else: {Map.put(acc1, key, value), value + acc2}
end)
WARNING: This is an expensive operation, beware of using it in prod.
Sets the given value
under key
in the Cache.
It returns value
or Nebulex.Object.t
(depends on :return
option)
if the value has been successfully inserted.
Options
:on_conflict
- It may be one of:raise
(the default),:nothing
,:replace
. See the “OnConflict” section for more information.
See the “Shared options” section at the module documentation.
Example
%Nebulex.Object{key: :a} =
MyCache.set :a, "anything", ttl: 100000, return: :object
OnConflict
The :on_conflict
option supports the following values:
:raise
- raises if there is a conflicting key:nothing
- ignores the error in case of conflicts:replace
- replace the value on the existing key with the givenvalue
Examples
# Set twice
%Nebulex.Object{key: :a, version: v1} = MyCache.set :a, 1, return: :object
%Nebulex.Object{key: :a, version: v2}
MyCache.set :a, 2, return: :object, version: v1
# Set with the same key and wrong version but do nothing on conflicts.
# Keep in mind that, although this returns successfully, the returned
# struct does not reflect the data in the Cache. For instance, in case
# of "on_conflict: :nothing", the returned object isn't set.
%Nebulex.Object{key: :a, value: 2} =
MyCache.set :a, 3, return: :object, version: v1, on_conflict: :nothing
2 = MyCache.get :a
# Set with the same key and wrong version but replace the current
# value on conflicts.
3 = MyCache.set :a, 3, version: v1, on_conflict: :replace
3 = MyCache.get :a
Returns the cache size (total number of cached entries).
Examples
for x <- 1..10, do: MyCache.set(x, x)
10 = MyCache.size
for x <- 1..5, do: MyCache.delete(x)
5 = MyCache.size
start_link(opts()) :: {:ok, pid()} | {:error, {:already_started, pid()}} | {:error, term()}
Starts a supervision and return {:ok, pid}
or just :ok
if nothing
needs to be done.
Returns {:error, {:already_started, pid}}
if the cache is already
started or {:error, term}
in case anything else goes wrong.
Options
See the configuration in the moduledoc for options shared between adapters, for adapter-specific configuration see the adapter’s documentation.
Shuts down the cache represented by the given pid.
Returns a map with all cache entries (key/value). If you want the map values
be the cache object, pass the option :return
set to :object
.
Options
See the “Shared options” section at the module documentation.
Examples
for x <- 1..3, do: MyCache.set(x, x*2)
%{1 => 2, 2 => 4, 3 => 6} = MyCache.to_map
%Nebulex.Object{key: 1} = Map.get(MyCache.to_map(return: :object), 1)
WARNING: This is an expensive operation, beware of using it in prod.
transaction(function :: (... -> any()), opts()) :: any()
Runs the given function inside a transaction.
A successful transaction returns the value returned by the function.
Options
See the “Shared options” section at the module documentation.
Examples
MyCache.transaction fn ->
1 = MyCache.set(:a, 1)
true = MyCache.has_key?(:a)
MyCache.get(:a)
end
Updates the cached key
with the given function.
If key
is present in Cache with value value
, fun
is invoked with
argument value
and its result is used as the new value of key
.
If key
is not present in Cache, initial
is inserted as the value
of key
.
Options
:on_conflict
- same as callbackget/2
.
Note that for this function :return
option hasn’t any effect,
since it always returns the object value.
See the “Shared options” section at the module documentation.
Examples
1 = MyCache.update(:a, 1, &(&1 * 2))
2 = MyCache.update(:a, 1, &(&1 * 2))
Updates (increment or decrement) the counter mapped to the given key
.
If incr >= 0
then the current value is incremented by that amount,
otherwise the current value is decremented.
If incr
is not a valid integer, then an ArgumentError
exception
is raised.
Options
See the “Shared options” section at the module documentation.
Examples
1 = MyCache.update_counter(:a)
3 = MyCache.update_counter(:a, 2)
2 = MyCache.update_counter(:a, -1)
%Nebulex.Object{key: :a, value: 2} = MyCache.update_counter(:a, 0, return: :object)