Nebulex v1.0.0-rc.3 Nebulex.Adapters.Multilevel View Source

Adapter module for Multi-level Cache.

This is just a simple layer on top of local or distributed cache implementations that enables to have a cache hierarchy by levels. Multi-level caches generally operate by checking the fastest, level 1 (L1) cache first; if it hits, the adapter proceeds at high speed. If that first cache misses, the next fastest cache (level 2, L2) is checked, and so on, before accessing external memory (that can be handled by a :fallback function).

Beware this behaviour only takes place for get/3 function, rest of the functions behaves most like a bypass.

Options

These options should be set in the config file and require recompilation in order to make an effect.

  • :adapter - The adapter name, in this case, Nebulex.Adapters.Multilevel

  • :cache_model - Specifies the cache model: :inclusive or :exclusive; defaults to :inclusive. In an inclusive cache, the same data can be present in all caches/levels. In an exclusive cache, data can be present in only one cache/level and a key cannot be found in the rest of caches at the same time. This option affects get operation only.

  • :levels - The list of caches where each cache corresponds to a level. The order of the caches in the list defines the the order of the levels as well, for example, the first cache in the list will be the L1 cache (level 1) and so on; the Nth elemnt will be the LN cache. This option is mandatory, if it is not set or empty, an exception will be raised.

  • :fallback - Defines a fallback function when a key is not present in any cache level. Function is defined as: (key -> value).

The :fallback can be defined in two ways: at compile-time and at run-time. At compile-time, in the cache config, set the module that implements the function:

config :my_app, MyApp.MultilevelCache,
  fallback: &MyMapp.AnyModule/1

And at run-time, passing the function as an option within the opts argument (only valid for get function):

MultilevelCache.get("foo", fallback: fn(key) -> key * 2 end)

Shared Options

Some functions below accept the following options:

  • :level - It may be an integer greater than 0 that specifies the cache level where the operation will take place, or it may be also :all to execute the operation in all cache levels. By default it’s set to 1, which means the set will only be evaluated at the first cache level.

Example

Nebulex.Cache is the wrapper around the Cache. We can define the multi-level cache as follows:

defmodule MyApp.MultilevelCache do
  use Nebulex.Cache, otp_app: :nebulex, adapter: Nebulex.Adapters.Multilevel

  defmodule L1 do
    use Nebulex.Cache, otp_app: :nebulex, adapter: Nebulex.Adapters.Local
  end

  defmodule L2 do
    use Nebulex.Cache, otp_app: :nebulex, adapter: Nebulex.Adapters.Dist
  end

  def fallback(_key) do
    # maybe fetch the data from Database
    nil
  end
end

defmodule MyApp.LocalCache do
  use Nebulex.Cache, otp_app: :my_app, adapter: Nebulex.Adapters.Local
end

Where the configuration for the Cache must be in your application environment, usually defined in your config/config.exs:

config :my_app, MyApp.MultilevelCache,
  levels: [
    MyApp.MultilevelCache.L1,
    MyApp.MultilevelCache.L2
  ],
  fallback: &MyApp.MultilevelCache.fallback/1

config :my_app, MyApp.MultilevelCache.L1,
  n_shards: 2,
  gc_interval: 3600

config :my_app, MyApp.MultilevelCache.L2,
  local: MyApp.LocalCache

config :my_app, MyApp.LocalCache,
  n_shards: 2,
  gc_interval: 3600

Extended API

This adapter provides some additional functions to the Nebulex.Cache API.

__levels__

This function returns the configured level list.

MyCache.__levels__

__model__

This function returns the multi-level cache model.

MyCache.__model__

__fallback__

This function returns the default fallback function.

MyCache.__fallback__

Limitations

Because this adapter reuses other existing/configured adapters, it inherits all their limitations too. Therefore, it is highly recommended to check the documentation of the used adapters.

Link to this section Summary

Functions

Deletes the cached entry in for a specific key

Flushes all cache levels

Retrieves the requested key (if it exists) checking the fastest, level 1 (L1) cache first; if it hits, the adapter proceeds at high speed. If that first cache misses, the next fastest cache (level 2, L2) is checked, and so on, before accessing external memory (that can be handled by the :fallback function)

Gets the value from key and updates it, all in one pass

Evaluates this operation on each cache level until get a non-empty result (different from nil or false), otherwise it returns the latest obtained result (last cache level)

Returns true if the given process is inside a transaction in any of the cache levels

Returns all cached keys in all cache levels

Evaluates this operation on each cache level until get a non-empty result (different from nil or false), otherwise it returns the latest obtained result (last cache level)

Execute the reduce function in all cache levels

Sets the given value under key in the Cache

Returns the total number of entries in all cache levels

Returns a map with all cached entries in all cache levels

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 Functions

Link to this function delete(cache, key, opts) View Source

Deletes the cached entry in for a specific key.

Options

  • :level - Check shared options in module documentation.

Example

# Entry is deleted from first cache level
MyCache.delete("foo")

# Entry is deleted from second cache level
MyCache.delete("foo", level: 2)

# Entry is deleted from all cache levels
MyCache.delete("foo", level: :all)

Flushes all cache levels.

Examples

MyCache.flush

Retrieves the requested key (if it exists) checking the fastest, level 1 (L1) cache first; if it hits, the adapter proceeds at high speed. If that first cache misses, the next fastest cache (level 2, L2) is checked, and so on, before accessing external memory (that can be handled by the :fallback function).

If :cache_model is :inclusive, when the key is found in a level N, that entry is duplicated backwards (to all previous levels: 1..N-1).

Options

  • :fallback - Defines a fallback function when a key is not present in any cache level. Function is defined as: (key -> value).

See the “Shared options” section at the module documentation and alse Nebulex.Cache.

Example

MyCache.get("foo", fallback: fn(_key) ->
  # Maybe fetch the key from database
  "initial value"
end)
Link to this function get_and_update(cache, key, fun, opts) View Source

Gets the value from key and updates it, all in one pass.

Options

  • :level - Check shared options in module documentation.

Example

{nil, "value!"} = MyCache.get_and_update(:a, fn current_value ->
  {current_value, "value!"}
end, level: :all)

Evaluates this operation on each cache level until get a non-empty result (different from nil or false), otherwise it returns the latest obtained result (last cache level).

Examples

MyCache.has_key?(:a)

Returns true if the given process is inside a transaction in any of the cache levels.

Returns all cached keys in all cache levels.

Examples

MyCache.keys

Evaluates this operation on each cache level until get a non-empty result (different from nil or false), otherwise it returns the latest obtained result (last cache level).

Examples

MyCache.pop(:a)
Link to this function reduce(cache, acc_in, fun, opts) View Source

Execute the reduce function in all cache levels.

Examples

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)
Link to this function set(cache, key, value, opts) View Source

Sets the given value under key in the Cache.

Options

  • :level - Check shared options in module documentation.

Example

# Entry is set at first cache level
MyCache.set("foo", "bar")

# Entry is set at second cache level
MyCache.set("foo", "bar", level: 2)

# Entry is set in all cache levels
MyCache.set("foo", "bar", level: :all)

Returns the total number of entries in all cache levels.

Examples

MyCache.size

Returns a map with all cached entries in all cache levels.

Examples

MyCache.to_map
Link to this function transaction(cache, opts, fun) View Source

Runs the given function inside a transaction.

A successful transaction returns the value returned by the function.

Options

  • :level - Check shared options in module documentation.

Example

MyCache.transaction(fn ->
  1 = MyCache.set(:a, 1)
  true = MyCache.has_key?(:a)
  MyCache.get(:a)
end)
Link to this function update(cache, key, initial, fun, opts) View Source

Updates the cached key with the given function.

Options

  • :level - Check shared options in module documentation.

Example

MyCache.update(:a, 1, &(&1 * 2), level: :all)
Link to this function update_counter(cache, key, incr, opts) View Source

Updates (increment or decrement) the counter mapped to the given key.

Options

  • :level - Check shared options in module documentation.

Example

# Counter is incremented at first cache level
MyCache.update_counter("foo", "bar")