Cashmere behaviour (Cashmere v0.1.0) View Source
This module provides the interface to work with Cashmere, a high performance in-memory caching solution.
To get started with Cashmere, you need to create a module that calls
use Cashmere
, like this:
defmodule MyApp.Cache do
use Cashmere, purge_interval: _milliseconds = 100, partitions: 4
end
This way, MyApp.Cache
becomes a Cashmere cache with four partitions. It
comes with the child_spec/1
function that returns child specification
that allows us to start MyApp.Cache
directly under a supervision tree,
and many other functions to work with the cache as documented in this
module.
Usually you won't call child_spec/1
directly but just add the cache to the
application supervision tree.
def start(_type, _args) do
children = [
MyApp.Cache,
# ...
]
Supervisor.start_link(children, strategy: :one_for_one)
end
There are a few configuration values available for use Cashmere
:
purge_interval
— (required) the interval in milliseconds when expired items in the cache are purged. Note that intervals are not exact, but at least as long as the interval is passed.partitions
— the amount of paritions of this cache. Defaults to1
.
Link to this section Summary
Callbacks
Returns a specification to start the cache under a supervisor.
Retrieves the value stored under key
, invokes value_fetcher
if not found, and
puts the returned value in the cache under key
, with the specified expiration
.
Retrieves the value by a specific key
from the cache.
Puts the given value
under key
in the cache, with the specified expiration
.
Retrieves the value stored under key
, invokes value_fetcher
serializably if
not found, and puts the returned value in the cache under key
, with the specified
expiration
.
Link to this section Types
Specs
expiration() :: pos_integer() | :infinity
Expiration time (in milliseconds or :infinity
).
Specs
key() :: any()
Specs
value() :: any()
Link to this section Callbacks
Specs
child_spec(options :: Keyword.t()) :: Supervisor.child_spec()
Returns a specification to start the cache under a supervisor.
See the "Child specification" section in the Supervisor
module for more detailed information.
Specs
dirty_read( key(), expiration(), value_fetcher :: (() -> {:ok, result} | {:error, reason}) ) :: {:ok, result} | {:error, reason} when result: value(), reason: any()
Retrieves the value stored under key
, invokes value_fetcher
if not found, and
puts the returned value in the cache under key
, with the specified expiration
.
Note that, since value_fetcher
will always be invoked in case of a cache miss,
this function is subjected to cascading failures under very high load.
Use read/3
if you need serializable invocation.
Examples
iex> MyApp.Cache.dirty_read(:name, 30_000, fn ->
...> very_heavy_computation()
...> end)
{:ok, "cashmere"}
Specs
Retrieves the value by a specific key
from the cache.
Examples
iex> MyApp.Cache.get(:name)
{:ok, "cashmere"}
iex> MyApp.Cache.get(:does_not_exist)
:error
Specs
put(key(), value(), expiration()) :: :ok
Puts the given value
under key
in the cache, with the specified expiration
.
To put a value that never expires, use :infinity
for expiration
.
Note that entries in the cache are purged periodically with the configured purge_interval
,
it's possible for the value to exist for a short while after the given expiration time.
Examples
iex> MyApp.Cache.put(:name, "cashmere", _30_seconds = 30_000)
:ok
Specs
read( key(), expiration(), value_fetcher :: (() -> {:ok, result} | {:error, reason}) ) :: {:ok, value() | result} | {:error, reason} | {:error, {:cache, :callback_failure}} | {:error, {:cache, :retry_failure}} when result: value(), reason: any()
Retrieves the value stored under key
, invokes value_fetcher
serializably if
not found, and puts the returned value in the cache under key
, with the specified
expiration
.
"Serializably" means that there will be only one invocation of value_fetcher
at
a point in time, amongst many concurrent read/3
calls with the same key
, in the
current runtime instance. This can be used as a possible mitigation for
cache stampedes under very high load,
to help avoiding cascading failures under very high load when massive cache misses
happen for hot keys.
Note that this function is subjected to some minor performance overhead. Most of the
time when it is not necessary, consider using dirty_read/3
.
There are several possible errors:
{:cache, :callback_failure}
— the invocation ofvalue_fetcher
raised an exception.{:cache, :retry_failure}
— the invocation ofvalue_fetcher
succeeded but the value could not be retrieved.reason
— the invocation ofvalue_fetcher
returned an error withreason
.
Examples
iex> MyApp.Cache.read(:name, 30_000, fn ->
...> very_heavy_computation()
...> end)
{:ok, "cashmere"}