View Source Cache behaviour (elixir_cache v0.1.1)

ElixirCache

Hex version badge Test Credo Dialyzer Coverage

The goal of this project is to unify Cache APIs and make Strategies easy to implement and sharable across all storage types/adapters

The second goal is to make sure testing of all cache related funciions is easy, meaning caches should be isolated per test and not leak their state to outside tests

installation

Installation

The package can be installed by adding elixir_cache to your list of dependencies in mix.exs:

def deps do
  [
    {:elixir_cache, "~> 0.1.0"}
  ]
end

The docs can be found at https://hexdocs.pm/elixir_cache.

usage

Usage

defmodule MyModule do
  use Cache,
    adapter: Cache.Redis,
    name: :my_name,
    sandbox?: Mix.env() === :test,
    opts: [...opts]
end

In our application.ex

children = [
  {Cache, [MyModule]}
]

Now we can use MyModule to call various Cache apis

MyModule.get("key") #> {:ok, nil}
MyModule.put("key", "value") #> :ok
MyModule.get("key") #> {:ok, "value"}

Adapter Specific Functions

Some adapters have specific functions such as redis which has hash functions and pipeline functions to make calls easier.

These adapter when used will add extra commands to your cache module.

sandboxing

Sandboxing

Our cache config accepts a sandbox?: boolean, in sanbox mode, the Cache.Sandbox adapter will be used which is just a simple Agent cache which is unique to the root process. All subprocesses will also have access to the same cache but it will be isolated by root process. This means in test mode, each process has it's own cache and is isolated from other tests, allowing you to run all your tests asynchronously

creating-adapters

Creating Adapters

Adapters are very easy to create in this model and are basically just a module that implement the @behaviour Cache

This behaviour adds the following callbacks

put(cache_name, key, ttl, value, opts \\ [])
get(cache_name, key, opts \\ [])
delete(cache_name, key, opts \\ [])
opts_definition() # NimbleOptions definition map
child_spec({cache_name, cache_opts})

Cache.ETS is probably the easiest adapter to follow as a guide as it's a simple Task

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Callback implementation for Supervisor.init/1.

Link to this section Callbacks

@callback child_spec({cache_name :: atom(), cache_opts :: Keyword.t()}) ::
  Supervisor.child_spec() | :supervisor.child_spec()
@callback delete(cache_name :: atom(), key :: atom() | String.t()) ::
  :ok | ErrorMessage.t()
Link to this callback

delete(cache_name, key, opts)

View Source
@callback delete(cache_name :: atom(), key :: atom() | String.t(), opts :: Keyword.t()) ::
  :ok | ErrorMessage.t()
@callback get(cache_name :: atom(), key :: atom() | String.t()) ::
  ErrorMessage.t_res(any())
@callback get(cache_name :: atom(), key :: atom() | String.t(), Keyword.t()) ::
  ErrorMessage.t_res(any())
@callback opts_definition() :: Keyword.t()
Link to this callback

put(cache_name, key, ttl, value)

View Source
@callback put(
  cache_name :: atom(),
  key :: atom() | String.t(),
  ttl :: pos_integer(),
  value :: any()
) ::
  :ok | ErrorMessage.t()
Link to this callback

put(cache_name, key, ttl, value, t)

View Source
@callback put(
  cache_name :: atom(),
  key :: atom() | String.t(),
  ttl :: pos_integer(),
  value :: any(),
  Keyword.t()
) :: :ok | ErrorMessage.t()

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Callback implementation for Supervisor.init/1.

Link to this function

start_link(cache_children, opts \\ [])

View Source