Mnemonix v0.4.0 Mnemonix.Store.Behaviour
Main point of entry for implementing new Mnemonix.Stores.
To create new store, you simply use this module as a meta-behaviour that brings in many others.
It will implement start_link/1
, start_link/2
, and start_link/3
functions
and bring in the actual Mnemonix
behaviours:
Mnemonix.Core.Behaviour
: required callbacks with no default implementation a store must provideMnemonix.Lifecycle.Behaviour
: support forc:GenServer:init/1
andc:GenServer:terminate/2
Mnemonix.Map.Behaviour
: support for map operationsMnemonix.Expiry.Behaviour
: support for expires/persist operationsMnemonix.Bump.Behaviour
: support for increment/decrement operations
These behaviours may have required callbacks you need to implement for the store to work, and optional callbacks with default implementations that leverage the required ones to make the store fully featured.
Core Callbacks
Currently the callbacks you must implement for a full-featured store are:
c:Mnemonix.Core.Behaviour.setup/1
c:Mnemonix.Core.Behaviour.delete/2
c:Mnemonix.Core.Behaviour.fetch/2
c:Mnemonix.Core.Behaviour.put/3
All other Mnemonix
functions can be implemented in terms of them.
Optional Callbacks
Every single Mnemonix
function/arity combo has a corresponding callback.
Those that are not required have default implementations, normally in terms of the core ones.
However, these implementations are all marked as overridable,
so if the store you are building offers native support for an operation,
you can call it directly to provide a more efficient implementation.
If any these callbacks don’t make sense to implement in the context of the store you’re developing,
feel free to override them to raise an exception when they are used.
Most callbacks are expected to return some variant of {:ok, updated_store, return_value}
,
but if they return {:error, ExceptionModule, args}
,
it will raise the exception at the Mnemonix
call site,
keeping the store process alive.
Building a Store
Mnemonix.Map.Store
exists mostly to provide a reference implementation for store developers,
demonstrating the minimum necessary to get a store working.
Mnemonix.ETS.Store
is a good example of a store that requires more complicated initialization logic.
Mnemonix.Redix.Store
is a good example of a store that overrides optional callbacks
with native support for Mnemonix.Expiry.Behaviour
and Mnemonix.Bump.Behaviour
.
Adding Capabilities to Mnemonix
Mnemonix is powered by a non-trivial set of interfaces. If you want to contribute functionality
to the core Mnemonix
module, you must understand how they all work. Reading the source code
is the best way to do this, but here’s a high level overview.
Mnemonix.Store
Every Mnemonix.Store
is just a GenServer
with a very particular interface and state.
Mnemonix.Store.start_link
When the store is started, it goes through an initialization pipeline provided by init/1
.
First it invokes c:Mnemonix.Lifecycle.Behaviour.setup/1
to prepare private internal state
from user-provided options, then it allows utilities to do feature-specific setup in extra callbacks
like c:Mnemonix.Expiry.Behaviour.setup_expiry/1
.
The Mnemonix.Store struct
The state of the Mnemonix.Store
server, and result of init/1
, is a struct containing:
impl:
the underlying store module to make calls toopts:
the options this store was configured with ininit/1
state:
the store-specific result ofc:Mnemonix.Lifecycle.Behaviour.setup/1
expiry:
the store-specific result ofc:Mnemonix.Expiry.Behaviour.setup_expiry/1
Mnemonix
=> Mnemonix.Store
Mnemonix
functions invoke GenServer.call/3
.