View Source Cachex (Cachex v4.0.2)

Cachex provides a straightforward interface for in-memory key/value storage.

Cachex is an extremely fast, designed for caching but also allowing for more general in-memory storage. The main goal of Cachex is achieve a caching implementation with a wide array of options, without sacrificing performance. Internally, Cachex is backed by ETS, allowing for an easy-to-use interface sitting upon extremely well tested tools.

Cachex comes with support for all of the following (amongst other things):

  • Time-based key expirations
  • Maximum size protection
  • Pre/post execution hooks
  • Proactive/reactive cache warming
  • Transactions and row locking
  • Asynchronous write operations
  • Distribution across app nodes
  • Syncing to a local filesystem
  • Idiomatic cache streaming
  • Batched write operations
  • User command invocation
  • Statistics gathering

All features are optional to allow you to tune based on the throughput needed.

Please see Cachex.start_link/2 inside the Cachex documentation for further details about how to configure these options and example usage.

Summary

Functions

Returns a specification to start this module under a supervisor.

Removes all entries from a cache.

Decrements an entry in the cache.

Removes an entry from a cache.

Determines whether a cache contains any entries.

Executes multiple functions in the context of a cache.

Determines whether an entry exists in a cache.

Places an expiration time on an entry in a cache.

Updates an entry in a cache to expire at a given time.

Exports all entries from a cache.

Fetches an entry from a cache, generating a value on cache miss.

Retrieves an entry from a cache.

Retrieves and updates an entry in a cache.

Imports an export set into a cache.

Increments an entry in the cache.

Inspects various aspects of a cache.

Invokes a custom command against a cache entry.

Retrieves a list of all entry keys from a cache.

Removes an expiration time from an entry in a cache.

Prunes to a maximum size of records in a cache.

Triggers a cleanup of all expired entries in a cache.

Places an entry in a cache.

Places a batch of entries in a cache.

Refreshes an expiration for an entry in a cache.

Resets a cache by clearing the keyspace and restarting any hooks.

Deserializes a cache from a location on a filesystem.

Serializes a cache to a location on a filesystem.

Retrieves the total size of a cache.

Creates a new Cachex cache service tree.

Creates a new Cachex cache service tree, linked to the current process.

Retrieves statistics about a cache.

Takes an entry from a cache.

Updates the last write time on a cache entry.

Executes multiple functions in the context of a transaction.

Retrieves the expiration for an entry in a cache.

Updates an entry in a cache.

Triggers a manual warming in a cache.

Types

@type status() :: :ok | :error
@type t() :: atom() | Cachex.Spec.cache()

Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

clear(cache, options \\ [])

View Source
@spec clear(t(), Keyword.t()) :: {status(), integer()}

Removes all entries from a cache.

The returned numeric value will contain the total number of keys removed from the cache. This is equivalent to running size/2 before running the internal clear operation.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.get(:my_cache, "key")
iex> Cachex.size(:my_cache)
{ :ok, 1 }

iex> Cachex.clear(:my_cache)
{ :ok, 1 }

iex> Cachex.size(:my_cache)
{ :ok, 0 }
Link to this function

decr(cache, key, amount \\ 1, options \\ [])

View Source
@spec decr(t(), any(), integer(), Keyword.t()) :: {status(), integer()}

Decrements an entry in the cache.

This will overwrite any value that was previously set against the provided key.

Options

  • :default

    An initial value to set the key to if it does not exist. This will take place before the decrement call. Defaults to 0.

Examples

iex> Cachex.put(:my_cache, "my_key", 10)
iex> Cachex.decr(:my_cache, "my_key")
{ :ok, 9 }

iex> Cachex.put(:my_cache, "my_new_key", 10)
iex> Cachex.decr(:my_cache, "my_new_key", 5)
{ :ok, 5 }

iex> Cachex.decr(:my_cache, "missing_key", 5, default: 2)
{ :ok, -3 }
Link to this function

del(cache, key, options \\ [])

View Source
@spec del(t(), any(), Keyword.t()) :: {status(), boolean()}

Removes an entry from a cache.

This will return { :ok, true } regardless of whether a key has been removed or not. The true value can be thought of as "is key no longer present?".

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.get(:my_cache, "key")
{ :ok, "value" }

iex> Cachex.del(:my_cache, "key")
{ :ok, true }

iex> Cachex.get(:my_cache, "key")
{ :ok, nil }
Link to this function

empty?(cache, options \\ [])

View Source
@spec empty?(t(), Keyword.t()) :: {status(), boolean()}

Determines whether a cache contains any entries.

This does not take the expiration time of keys into account. As such, if there are any unremoved (but expired) entries in the cache, they will be included in the returned determination.

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
iex> Cachex.empty?(:my_cache)
{ :ok, false }

iex> Cachex.clear(:my_cache)
iex> Cachex.empty?(:my_cache)
{ :ok, true }
Link to this function

execute(cache, operation, options \\ [])

View Source
@spec execute(t(), function(), Keyword.t()) :: {status(), any()}

Executes multiple functions in the context of a cache.

This can be used when carrying out several cache operations at once to avoid the overhead of cache loading and jumps between processes.

This does not provide a transactional execution, it simply avoids the overhead involved in the initial calls to a cache. For a transactional implementation, please see transaction/3.

To take advantage of the cache context, ensure to use the cache instance provided when executing cache calls. If this is not done you will see zero benefits from using execute/3.

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
iex> Cachex.put(:my_cache, "key2", "value2")
iex> Cachex.execute(:my_cache, fn(worker) ->
...>   val1 = Cachex.get!(worker, "key1")
...>   val2 = Cachex.get!(worker, "key2")
...>   [val1, val2]
...> end)
{ :ok, [ "value1", "value2" ] }
Link to this function

exists?(cache, key, options \\ [])

View Source
@spec exists?(t(), any(), Keyword.t()) :: {status(), boolean()}

Determines whether an entry exists in a cache.

This will take expiration times into account, meaning that expired entries will not be considered to exist.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.exists?(:my_cache, "key")
{ :ok, true }

iex> Cachex.exists?(:my_cache, "missing_key")
{ :ok, false }
Link to this function

expire(cache, key, expiration, options \\ [])

View Source
@spec expire(t(), any(), number() | nil, Keyword.t()) :: {status(), boolean()}

Places an expiration time on an entry in a cache.

The provided expiration must be a integer value representing the lifetime of the entry in milliseconds. If the provided value is not positive, the entry will be immediately evicted.

If the entry does not exist, no changes will be made in the cache.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.expire(:my_cache, "key", :timer.seconds(5))
{ :ok, true }

iex> Cachex.expire(:my_cache, "missing_key", :timer.seconds(5))
{ :ok, false }
Link to this function

expire_at(cache, key, timestamp, options \\ [])

View Source
@spec expire_at(t(), any(), number(), Keyword.t()) :: {status(), boolean()}

Updates an entry in a cache to expire at a given time.

Unlike expire/4 this call uses an instant in time, rather than a duration. The same semantics apply as calls to expire/4 in that instants which have passed will result in immediate eviction.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.expire_at(:my_cache, "key", 1455728085502)
{ :ok, true }

iex> Cachex.expire_at(:my_cache, "missing_key", 1455728085502)
{ :ok, false }
Link to this function

export(cache, options \\ [])

View Source
@spec export(t(), Keyword.t()) :: {status(), [Cachex.Spec.entry()]}

Exports all entries from a cache.

This provides a raw read of the entire backing table into a list of cache records for export purposes.

This function is very heavy, so it should typically only be used when debugging and/or exporting of tables (although the latter case should really use Cachex.save/3).

## Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.export(:my_cache)
{ :ok, [ { :entry, "key", 1538714590095, nil, "value" } ] }
Link to this function

fetch(cache, key, fallback, options \\ [])

View Source
@spec fetch(t(), any(), function(), Keyword.t()) ::
  {status() | :commit | :ignore, any()} | {:commit, any(), any()}

Fetches an entry from a cache, generating a value on cache miss.

If the entry requested is found in the cache, this function will operate in the same way as get/3. If the entry is not contained in the cache, the provided fallback function will be executed.

A fallback function is a function used to lazily generate a value to place inside a cache on miss. Consider it a way to achieve the ability to create a read-through cache.

A fallback function should return a Tuple consisting of a :commit or :ignore tag and a value. If the Tuple is tagged :commit the value will be placed into the cache and then returned. If tagged :ignore the value will be returned without being written to the cache. If you return a value which does not fit this structure, it will be assumed that you are committing the value.

As of Cachex v3.6, you can also provide a third element in a :commit Tuple, to allow passthrough of options from within your fallback. The options supported in this list match the options you can provide to a call of put/4. An example is the :ttl option to set an expiration from directly inside your fallback.

If a fallback function has an arity of 1, the requested entry key will be passed through to allow for contextual computation. If a function has an arity of 2, the :provide option from the global :fallback cache option will be provided as the second argument. This is to allow easy state sharing, such as remote clients. If a function has an arity of 0, it will be executed without arguments.

If a cache has been initialized with a default fallback function in the :fallback option at cache startup, the third argument to this call becomes optional.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.fetch(:my_cache, "key", fn(key) ->
...>   { :commit, String.reverse(key) }
...> end)
{ :ok, "value" }

iex> Cachex.fetch(:my_cache, "missing_key", fn(key) ->
...>   { :ignore, String.reverse(key) }
...> end)
{ :ignore, "yek_gnissim" }

iex> Cachex.fetch(:my_cache, "missing_key", fn(key) ->
...>   { :commit, String.reverse(key) }
...> end)
{ :commit, "yek_gnissim" }

iex> Cachex.fetch(:my_cache, "missing_key_expires", fn(key) ->
...>   { :commit, String.reverse(key), expire: :timer.seconds(60) }
...> end)
{ :commit, "seripxe_yek_gnissim", [expire: 60000] }
Link to this function

get(cache, key, options \\ [])

View Source
@spec get(t(), any(), Keyword.t()) :: {atom(), any()}

Retrieves an entry from a cache.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.get(:my_cache, "key")
{ :ok, "value" }

iex> Cachex.get(:my_cache, "missing_key")
{ :ok, nil }
Link to this function

get_and_update(cache, key, updater, options \\ [])

View Source
@spec get_and_update(t(), any(), function(), Keyword.t()) ::
  {:commit | :ignore, any()}

Retrieves and updates an entry in a cache.

This operation can be seen as an internal mutation, meaning that any previously set expiration time is kept as-is.

This function accepts the same return syntax as fallback functions, in that if you return a Tuple of the form { :ignore, value }, the value is returned from the call but is not written to the cache. You can use this to abandon writes which began eagerly (for example if a key is actually missing)

See the fetch/4 documentation for more information on return formats.

Examples

iex> Cachex.put(:my_cache, "key", [2])
iex> Cachex.get_and_update(:my_cache, "key", &([1|&1]))
{ :commit, [1, 2] }

iex> Cachex.get_and_update(:my_cache, "missing_key", fn
...>   (nil) -> { :ignore, nil }
...>   (val) -> { :commit, [ "value" | val ] }
...> end)
{ :ignore, nil }
Link to this function

import(cache, entries, options \\ [])

View Source
@spec import(t(), Enumerable.t(), Keyword.t()) :: {status(), any()}

Imports an export set into a cache.

This provides a raw import of a previously exported cache via the use of the export/2 command.

## Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.import(:my_cache, [ { :entry, "key", "value", 1538714590095, nil } ])
{ :ok, 1 }
Link to this function

incr(cache, key, amount \\ 1, options \\ [])

View Source
@spec incr(t(), any(), integer(), Keyword.t()) :: {status(), integer()}

Increments an entry in the cache.

This will overwrite any value that was previously set against the provided key.

Options

  • :default

    An initial value to set the key to if it does not exist. This will take place before the increment call. Defaults to 0.

Examples

iex> Cachex.put(:my_cache, "my_key", 10)
iex> Cachex.incr(:my_cache, "my_key")
{ :ok, 11 }

iex> Cachex.put(:my_cache, "my_new_key", 10)
iex> Cachex.incr(:my_cache, "my_new_key", 5)
{ :ok, 15 }

iex> Cachex.incr(:my_cache, "missing_key", 5, default: 2)
{ :ok, 7 }
Link to this function

inspect(cache, option, options \\ [])

View Source
@spec inspect(t(), atom() | tuple(), Keyword.t()) :: {status(), any()}

Inspects various aspects of a cache.

These operations should be regarded as debug tools, and should really only happen outside of production code (unless absolutely) necessary.

Accepted options are only provided for convenience and should not be heavily relied upon. They are not part of the public interface (despite being documented) and as such may be removed at any time (however this does not mean that they will be).

Please use cautiously. inspect/2 is provided mainly for testing purposes and so performance isn't as much of a concern. It should also be noted that inspect/2 will always operate locally.

Options

  • :cache

    Retrieves the internal cache record for a cache.

  • { :entry, key }

    Retrieves a raw entry record from inside a cache.

  • { :expired, :count }

    Retrieves the number of expired entries which currently live in the cache but have not yet been removed by cleanup tasks (either scheduled or lazy).

  • { :expired, :keys }

    Retrieves the list of expired entry keys which current live in the cache but have not yet been removed by cleanup tasks (either scheduled or lazy).

  • { :janitor, :last }

    Retrieves metadata about the last execution of the Janitor service for the specified cache.

  • { :memory, :bytes }

    Retrieves an approximate memory footprint of a cache in bytes.

  • { :memory, :binary }

    Retrieves an approximate memory footprint of a cache in binary format.

  • { :memory, :words }

    Retrieve an approximate memory footprint of a cache as a number of machine words.

Examples

iex> Cachex.inspect(:my_cache, :cache)
{:ok,
  {:cache, :my_cache, %{}, {:expiration, nil, 3000, true}, {:fallback, nil, nil},
    {:hooks, [], []}, {:limit, nil, Cachex.Policy.LRW, 0.1, []}, false, []}}

iex> Cachex.inspect(:my_cache, { :entry, "my_key" } )
{ :ok, { :entry, "my_key", 1475476615662, 1, "my_value" } }

iex> Cachex.inspect(:my_cache, { :expired, :count })
{ :ok, 0 }

iex> Cachex.inspect(:my_cache, { :expired, :keys })
{ :ok, [ ] }

iex> Cachex.inspect(:my_cache, { :janitor, :last })
{ :ok, %{ count: 0, duration: 57, started: 1475476530925 } }

iex> Cachex.inspect(:my_cache, { :memory, :binary })
{ :ok, "10.38 KiB" }

iex> Cachex.inspect(:my_cache, { :memory, :bytes })
{ :ok, 10624 }

iex> Cachex.inspect(:my_cache, { :memory, :words })
{ :ok, 1328 }
Link to this function

invoke(cache, cmd, key, options \\ [])

View Source
@spec invoke(t(), atom(), any(), Keyword.t()) :: any()

Invokes a custom command against a cache entry.

The provided command name must be a valid command which was previously attached to the cache in calls to start_link/2.

Examples

iex> import Cachex.Spec
iex>
iex> Cachex.start_link(:my_cache, [
...>    commands: [
...>      last: command(type: :read, execute: &List.last/1)
...>    ]
...> ])
{ :ok, _pid }

iex> Cachex.put(:my_cache, "my_list", [ 1, 2, 3 ])
iex> Cachex.invoke(:my_cache, :last, "my_list")
{ :ok, 3 }
Link to this function

keys(cache, options \\ [])

View Source
@spec keys(t(), Keyword.t()) :: {status(), [any()]}

Retrieves a list of all entry keys from a cache.

The order these keys are returned should be regarded as unordered.

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
iex> Cachex.put(:my_cache, "key2", "value2")
iex> Cachex.put(:my_cache, "key3", "value3")
iex> Cachex.keys(:my_cache)
{ :ok, [ "key2", "key1", "key3" ] }

iex> Cachex.clear(:my_cache)
iex> Cachex.keys(:my_cache)
{ :ok, [] }
Link to this function

persist(cache, key, options \\ [])

View Source
@spec persist(t(), any(), Keyword.t()) :: {status(), boolean()}

Removes an expiration time from an entry in a cache.

Examples

iex> Cachex.put(:my_cache, "key", "value", expiration: 1000)
iex> Cachex.persist(:my_cache, "key")
{ :ok, true }

iex> Cachex.persist(:my_cache, "missing_key")
{ :ok, false }
Link to this function

prune(cache, size, options \\ [])

View Source
@spec prune(t(), integer(), Keyword.t()) :: {status(), boolean()}

Prunes to a maximum size of records in a cache.

Pruning is done via a Least Recently Written (LRW) approach, determined by the modification time inside each cache record to avoid storing additional state.

For full details on this feature, please see the section of the documentation related to limitation of caches.

Options

  • :buffer

    Allows customization of the internal batching when paginating the cursor coming back from ETS. It's unlikely this will ever need changing.

  • :reclaim

    Provides control over thrashing by evicting an additonal number of cache entries beyond the maximum size. This option accepts a percentage (as a decimal) of extra keys to evict, to provide buffer between pruning passes. Defaults to 0.1 (i.e. 10%).

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
{ :ok, true }

iex> :timer.sleep(1)
:ok

iex> Cachex.put(:my_cache, "key2", "value2")
{ :ok, true }

iex> Cachex.prune(:my_cache, 1, reclaim: 0)
{ :ok, true }

iex> Cachex.keys(:my_cache)
{ :ok, [ "key2"] }
Link to this function

purge(cache, options \\ [])

View Source
@spec purge(t(), Keyword.t()) :: {status(), number()}

Triggers a cleanup of all expired entries in a cache.

This can be used to implement custom eviction policies rather than relying on the internal Janitor service. Take care when using this method though; calling purge/2 manually will result in a purge firing inside the calling process.

Examples

iex> Cachex.purge(:my_cache)
{ :ok, 15 }
Link to this function

put(cache, key, value, options \\ [])

View Source
@spec put(t(), any(), any(), Keyword.t()) :: {status(), boolean()}

Places an entry in a cache.

This will overwrite any value that was previously set against the provided key, and overwrite any TTLs which were already set.

Options

  • :expire

    An expiration value to set for the provided key (time-to-live), overriding any default expirations set on a cache. This value should be in milliseconds.

Examples

iex> Cachex.put(:my_cache, "key", "value")
{ :ok, true }

iex> Cachex.put(:my_cache, "key", "value", expire: :timer.seconds(5))
iex> Cachex.ttl(:my_cache, "key")
{ :ok, 5000 }
Link to this function

put_many(cache, pairs, options \\ [])

View Source
@spec put_many(t(), [{any(), any()}], Keyword.t()) :: {status(), boolean()}

Places a batch of entries in a cache.

This operates in the same way as put/4, except that multiple keys can be inserted in a single atomic batch. This is a performance gain over writing keys using multiple calls to put/4, however it's a performance penalty when writing a single key pair due to some batching overhead.

Options

  • :expire

    An expiration value to set for the provided keys (time-to-live), overriding any default expirations set on a cache. This value should be in milliseconds.

Examples

iex> Cachex.put_many(:my_cache, [ { "key", "value" } ])
{ :ok, true }

iex> Cachex.put_many(:my_cache, [ { "key", "value" } ], expire: :timer.seconds(5))
iex> Cachex.ttl(:my_cache, "key")
{ :ok, 5000 }
Link to this function

refresh(cache, key, options \\ [])

View Source
@spec refresh(t(), any(), Keyword.t()) :: {status(), boolean()}

Refreshes an expiration for an entry in a cache.

Refreshing an expiration will reset the existing expiration with an offset from the current time - i.e. if you set an expiration of 5 minutes and wait 3 minutes before refreshing, the entry will expire 8 minutes after the initial insertion.

Examples

iex> Cachex.put(:my_cache, "my_key", "my_value", expire: :timer.seconds(5))
iex> Process.sleep(4)
iex> Cachex.ttl(:my_cache, "my_key")
{ :ok, 1000 }

iex> Cachex.refresh(:my_cache, "my_key")
iex> Cachex.ttl(:my_cache, "my_key")
{ :ok, 5000 }

iex> Cachex.refresh(:my_cache, "missing_key")
{ :ok, false }
Link to this function

reset(cache, options \\ [])

View Source
@spec reset(t(), Keyword.t()) :: {status(), true}

Resets a cache by clearing the keyspace and restarting any hooks.

Options

  • :hooks

    A whitelist of hooks to reset on the cache instance (call the initialization phase of a hook again). This will default to resetting all hooks associated with a cache, which is usually the desired behaviour.

  • :only

    A whitelist of components to reset, which can currently contain either the :cache or :hooks tag to determine what to reset. This will default to [ :cache, :hooks ].

Examples

iex> Cachex.put(:my_cache, "my_key", "my_value")
iex> Cachex.reset(:my_cache)
iex> Cachex.size(:my_cache)
{ :ok, 0 }

iex> Cachex.reset(:my_cache, [ only: :hooks ])
{ :ok, true }

iex> Cachex.reset(:my_cache, [ only: :hooks, hooks: [ MyHook ] ])
{ :ok, true }

iex> Cachex.reset(:my_cache, [ only: :cache ])
{ :ok, true }
Link to this function

restore(cache, path, options \\ [])

View Source
@spec restore(t(), binary(), Keyword.t()) :: {status(), any()}

Deserializes a cache from a location on a filesystem.

This operation will read the current state of a cache from a provided location on a filesystem. This function will only understand files which have previously been created using Cachex.save/3.

It is the responsibility of the user to ensure that the location is able to be read from, not the responsibility of Cachex.

Options

  • :trust

    Allow for loading from trusted or untrusted sources; trusted sources can load atoms into the table, whereas untrusted sources cannot. Defaults to true.

Examples

iex> Cachex.put(:my_cache, "my_key", 10)
iex> Cachex.save(:my_cache, "/tmp/my_backup")
{ :ok, true }

iex> Cachex.size(:my_cache)
{ :ok, 1 }

iex> Cachex.clear(:my_cache)
iex> Cachex.size(:my_cache)
{ :ok, 0 }

iex> Cachex.restore(:my_cache, "/tmp/my_backup")
{ :ok, 1 }

iex> Cachex.size(:my_cache)
{ :ok, 1 }
Link to this function

save(cache, path, options \\ [])

View Source
@spec save(t(), binary(), Keyword.t()) :: {status(), any()}

Serializes a cache to a location on a filesystem.

This operation will write the current state of a cache to a provided location on a filesystem. The written state can be used alongside the Cachex.restore/3 command to import back in the future.

It is the responsibility of the user to ensure that the location is able to be written to, not the responsibility of Cachex.

Options

  • :buffer

    Allows customization of the internal batching when paginating the cursor coming back from ETS. It's unlikely this will ever need changing.

Examples

iex> Cachex.save(:my_cache, "/tmp/my_default_backup")
{ :ok, true }
Link to this function

size(cache, options \\ [])

View Source
@spec size(t(), Keyword.t()) :: {status(), number()}

Retrieves the total size of a cache.

By default this does not take expiration time of entries inside the cache into account, making it an O(1) call. This behaviour can be modified by passing expired: false to account for expirations, but please note that this is a much more involved calculation.

Options

  • :expired

    Whether or not to include expired records in the returned total. This is a boolean value which defaults to true.

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
iex> Cachex.put(:my_cache, "key2", "value2")
iex> Cachex.put(:my_cache, "key3", "value3", expire: 1)
iex> Cachex.size(:my_cache)
{ :ok, 3 }

iex> Cachex.size(:my_cache, expired: false)
{ :ok, 2 }
Link to this function

start(name, options \\ [])

View Source
@spec start(atom(), Keyword.t()) :: {atom(), pid()}

Creates a new Cachex cache service tree.

This will not link the cache to the current process, so if your process dies the cache will continue to live. If you don't want this behaviour, please use the provided Cachex.start_link/2.

This function is otherwise identical to start_link/2 so please see that documentation for further information and configuration.

Link to this function

start_link(name, options)

View Source
@spec start_link(atom(), Keyword.t()) :: {atom(), pid()}

Creates a new Cachex cache service tree, linked to the current process.

This will link the cache to the current process, so if your process dies the cache will also die. If you don't want this behaviour, please use start/2.

The first argument should be a unique atom, used as the name of the cache service for future calls through to Cachex. For all options requiring a record argument, please import Cachex.Spec in advance.

Options

  • :commands

    This option allows you to attach a set of custom commands to a cache in order to provide shorthand execution. A cache command must be constructed using the :command record provided by Cachex.Spec.

    A cache command will adhere to these basic rules:

    • If you define a :read command, the return value of your command will be passed through as the result of your call to invoke/4.
    • If you define a :write command, your command must return a two-element Tuple. The first element represents the value being returned from your invoke/4 call, and the second represents the value to write back into the cache (as an update). If your command does not fit this, errors will happen (intentionally).

    Commands are set on a per-cache basis, but can be reused across caches. They're set only on cache startup and cannot be modified after the cache tree is created.

    iex> import Cachex.Spec
    ...>
    ...> Cachex.start_link(:my_cache, [
    ...>   commands: [
    ...>     last: command(type:  :read, execute:   &List.last/1),
    ...>     trim: command(type: :write, execute: &String.trim/1)
    ...>   ]
    ...> ])
    { :ok, _pid }

    Either a Keyword or a Map can be provided against the :commands option as we only use Enum to verify them before attaching them internally. Please see the Cachex.Spec.command/1 documentation for further customization options.

  • :compressed

    This option will specify whether this cache should have enable ETS compression, which is likely to reduce memory overhead. Please note that there is a potential for this option to slow your cache due to compression overhead, so benchmark as appropriate when using this option. This option defaults to false.

    iex> Cachex.start_link(:my_cache, [ compressed: true ])
    { :ok, _pid }
  • :expiration

    The expiration option provides the ability to customize record expiration at a global cache level. The value provided here must be a valid :expiration record provided by Cachex.Spec.

    iex> import Cachex.Spec
    ...>
    ...> Cachex.start_link(:my_cache, [
    ...>   expiration: expiration(
    ...>     # how often cleanup should occur
    ...>     interval: :timer.seconds(30),
    ...>
    ...>     # default record expiration
    ...>     default: :timer.seconds(60),
    ...>
    ...>     # whether to enable lazy checking
    ...>     lazy: true
    ...>   )
    ...> ])
    { :ok, _pid }

    Please see the Cachex.Spec.expiration/1 documentation for further customization options.

  • :hooks

    The :hooks option allow the user to attach a list of notification hooks to enable listening on cache actions (either before or after they happen). These hooks should be valid :hook records provided by Cachex.Spec. Example hook implementations can be found in Cachex.Stats and Cachex.Policy.LRW.

    iex> import Cachex.Spec
    ...>
    ...> Cachex.start_link(:my_cache, [
    ...>   hooks: [
    ...>     hook(module: MyHook, name: :my_hook, args: { })
    ...>   ]
    ...> ])
    { :ok, _pid }

    Please see the Cachex.Spec.hook/1 documentation for further customization options.

  • :ordered

    This option will specify whether this cache should enable ETS ordering, which can improve performance if ordered traversal of a cache is required. Setting :ordered to true will result in both insert and lookup times being proportional to the logarithm of the number of objects in the table. This option defaults to false.

    iex> Cachex.start_link(:my_cache, [ ordered: true ])
    { :ok, _pid }
  • :router

    This option determines which module is used for cache routing inside distributed caches. You can provide either a full record structure or simply a module name.

    iex> import Cachex.Spec
    ...>
    ...> Cachex.start_link(:my_cache, [
    ...>   router: router(
    ...>     module: Cachex.Router.Jump,
    ...>     options: []
    ...>   )
    ...> ])
    { :ok, _pid }

    Please see the Cachex.Spec.router/1 documentation for further customization options.

  • :transactions

    This option will specify whether this cache should have transactions and row locking enabled from cache startup. Please note that even if this is false, it will be enabled the moment a transaction is executed. It's recommended to leave this as default as it will handle most use cases in the most performant way possible.

    iex> Cachex.start_link(:my_cache, [ transactions: true ])
    { :ok, _pid }
  • :warmers

    The :warmers option allows the user to attach a list of warming modules to a cache. These cache warmers must implement the Cachex.Warmer behaviour and are defined as warmer records.

    The only required value is the :module definition, although you can also choose to provide a name and state to attach to the warmer process. The flag :required is used to control whether the warmer must finish execution before the cache supervision tree can be considered fully started.

    iex> import Cachex.Spec
    ...>
    ...> Cachex.start_link(:my_cache, [
    ...>   warmers: [
    ...>     warmer(
    ...>       required: true,
    ...>       module: MyProject.DatabaseWarmer,
    ...>       state: connection,
    ...>       name: MyProject.DatabaseWarmer
    ...>     )
    ...>   ]
    ...> ])
    { :ok, _pid }

    Please see the Cachex.Spec.warmer/1 documentation for further customization options.

Link to this function

stats(cache, options \\ [])

View Source
@spec stats(t(), Keyword.t()) :: {status(), map()}

Retrieves statistics about a cache.

This will only provide statistics if the :stats option was provided on cache startup in start_link/2.

Examples

iex> Cachex.stats(:my_cache)
{:ok, %{meta: %{creation_date: 1518984857331}}}

iex> Cachex.stats(:cache_with_no_stats)
{ :error, :stats_disabled }
Link to this function

stream(cache, query \\ Q.build(where: Q.unexpired()), options \\ [])

View Source
@spec stream(t(), any(), Keyword.t()) :: {status(), Enumerable.t()}

Creates a Stream of entries in a cache.

This will stream all entries matching the match specification provided as the second argument. If none is provided, it will default to all entries which are yet to expire (in no particular order).

Consider using Cachex.Query to generate match specifications used when querying the contents of a cache table.

Options

  • :buffer

    Allows customization of the internal batching when paginating the cursor coming back from ETS. It's unlikely this will ever need changing.

Examples

iex> Cachex.put(:my_cache, "a", 1)
iex> Cachex.put(:my_cache, "b", 2)
iex> Cachex.put(:my_cache, "c", 3)
{:ok, true}

iex> :my_cache |> Cachex.stream! |> Enum.to_list
[{:entry, "b", 1519015801794, nil, 2},
  {:entry, "c", 1519015805679, nil, 3},
  {:entry, "a", 1519015794445, nil, 1}]

iex> query = Cachex.Query.build(output: :key)
iex> :my_cache |> Cachex.stream!(query) |> Enum.to_list
["b", "c", "a"]

iex> query = Cachex.Query.build(output: :value)
iex> :my_cache |> Cachex.stream!(query) |> Enum.to_list
[2, 3, 1]

iex> query = Cachex.Query.build(output: {:key, :value})
iex> :my_cache |> Cachex.stream!(query) |> Enum.to_list
[{"b", 2}, {"c", 3}, {"a", 1}]
Link to this function

take(cache, key, options \\ [])

View Source
@spec take(t(), any(), Keyword.t()) :: {status(), any()}

Takes an entry from a cache.

This is conceptually equivalent to running get/3 followed by an atomic del/3 call.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.take(:my_cache, "key")
{ :ok, "value" }

iex> Cachex.get(:my_cache, "key")
{ :ok, nil }

iex> Cachex.take(:my_cache, "missing_key")
{ :ok, nil }
Link to this function

touch(cache, key, options \\ [])

View Source
@spec touch(t(), any(), Keyword.t()) :: {status(), boolean()}

Updates the last write time on a cache entry.

This is very similar to refresh/3 except that the expiration time is maintained inside the record (using a calculated offset).

Link to this function

transaction(cache, keys, operation, options \\ [])

View Source
@spec transaction(t(), [any()], function(), Keyword.t()) :: {status(), any()}

Executes multiple functions in the context of a transaction.

This will operate in the same way as execute/3, except that writes to the specified keys will be blocked on the execution of this transaction.

The keys parameter should be a list of keys you wish to lock whilst your transaction is executed. Any keys not in this list can still be written even during your transaction.

Examples

iex> Cachex.put(:my_cache, "key1", "value1")
iex> Cachex.put(:my_cache, "key2", "value2")
iex> Cachex.transaction(:my_cache, [ "key1", "key2" ], fn(worker) ->
...>   val1 = Cachex.get(worker, "key1")
...>   val2 = Cachex.get(worker, "key2")
...>   [val1, val2]
...> end)
{ :ok, [ "value1", "value2" ] }
Link to this function

ttl(cache, key, options \\ [])

View Source
@spec ttl(t(), any(), Keyword.t()) :: {status(), integer() | nil}

Retrieves the expiration for an entry in a cache.

This is a millisecond value (if set) representing the time a cache entry has left to live in a cache. It can return nil if the entry does not have a set expiration.

Examples

iex> Cachex.ttl(:my_cache, "my_key")
{ :ok, 13985 }

iex> Cachex.ttl(:my_cache, "my_key_with_no_ttl")
{ :ok, nil }

iex> Cachex.ttl(:my_cache, "missing_key")
{ :ok, nil }
Link to this function

update(cache, key, value, options \\ [])

View Source
@spec update(t(), any(), any(), Keyword.t()) :: {status(), any()}

Updates an entry in a cache.

Unlike get_and_update/4, this does a blind overwrite of a value.

This operation can be seen as an internal mutation, meaning that any previously set expiration time is kept as-is.

Examples

iex> Cachex.put(:my_cache, "key", "value")
iex> Cachex.get(:my_cache, "key")
{ :ok, "value" }

iex> Cachex.update(:my_cache, "key", "new_value")
iex> Cachex.get(:my_cache, "key")
{ :ok, "new_value" }

iex> Cachex.update(:my_cache, "missing_key", "new_value")
{ :ok, false }
Link to this function

warm(cache, options \\ [])

View Source
@spec warm(t(), Keyword.t()) :: {status(), [atom()]}

Triggers a manual warming in a cache.

This allows for manual warming of a cache in situations where you already know the backing state has been updated. The return value of this function will contain the list of modules which were warmed as a result of this call.

Options

  • :only

    An optional list of modules to warm, acting as a whitelist. The default behaviour of this function is to trigger warming in all modules. You may provide either the module name, or the registered warmer name.

  • :wait

    Whether to wait for warmer completion or not, as a boolean. By default warmers are triggered to run in the background, but passing true here will block the return of this call until all warmers have completed.

Examples

iex> Cachex.warm(:my_cache)
{ :ok, [MyWarmer] }

iex> Cachex.warm(:my_cache, only: [MyWarmer])
{ :ok, [MyWarmer] }

iex> Cachex.warm(:my_cache, only: [])
{ :ok, [] }

iex> Cachex.warm(:my_cache, wait: true)
{ :ok, [MyWarmer]}