View Source ProcessHub.Service.Storage.Behaviour behaviour (ProcessHub v0.7.0)
Behaviour contract for ProcessHub registry storage backends.
A backend module implements the registry-table operations used by
ProcessHub.Service.ProcessRegistry. The default backend is
ProcessHub.Service.Storage.Ets (in-memory ETS). The DETS backend
(ProcessHub.Service.Storage.Dets) provides on-disk persistence so
the registry survives a coordinator restart.
All mutating callbacks return :ok | {:error, term()} rather than
booleans so a backend that may fail synchronously (timeout, no quorum,
IO error) can signal that without API churn. Read callbacks return
the value directly.
The ref/0 returned by open/2 is opaque to callers; each
backend chooses its own representation (an ETS tid, a DETS table
name, a custom client handle, etc.).
Summary
Types
Options accepted by insert/4.
An opaque handle returned by open/2. Backends choose their own
representation; callers MUST treat it as opaque.
Per-write options. sync: false applies the write but leaves its durable
sync to a later sync/1, so one sync can cover a batch of writes (group
commit). Absent, or sync: true, the write is durable on return.
Callbacks
Removes all entries.
Closes the registry storage. Implementations MUST flush any pending writes before returning.
Returns true when key is present (and not expired).
Returns all entries as a list. The shape mirrors the existing
:ets.tab2list/1 output: 2-tuples for entries without TTL and
3-tuples for entries with TTL. Expired entries are filtered.
Folds fun over all entries with initial accumulator acc.
Returns the value stored under key, or nil if the key is missing
or expired.
Inserts value under key. Returns :ok once the write is durable
for the backend's durability model (synchronous for DETS, in-memory
for ETS).
Inserts value under key with options.
Optional: inserts a batch of {key, value, opts} items with a single
write, so concurrent readers never observe a partially applied batch.
Backends that omit this callback get per-item inserts instead.
Optional: insert_many/2 taking write_opts(). A backend that implements
it together with sync/1 lets the registry group-commit: several writes
applied with sync: false, then one sync/1 that makes them all durable.
Returns the list of matches for match_expr. The shape matches the
current ProcessHub.Service.Storage.match/2 (a list of tuples, not a
list of lists).
Opens (and if necessary creates) the registry storage for the given hub.
Returns every non-expired row held in the backend's durable medium, as
{key, value} pairs, without inserting into, mutating, or otherwise affecting
the backend's live in-memory view.
Removes key.
Optional: remove/2 taking write_opts(); see insert_many/3.
Optional: makes every write applied with sync: false durable. Backends
without a durable medium need not implement it.
Types
@type insert_opts() :: [{:ttl, pos_integer()}] | keyword()
Options accepted by insert/4.
:ttl— time-to-live in milliseconds. When set, the entry is stored as{key, value, expire_ms}and reads filter expired entries.
@type ref() :: term()
An opaque handle returned by open/2. Backends choose their own
representation; callers MUST treat it as opaque.
@type write_opts() :: [{:sync, boolean()}]
Per-write options. sync: false applies the write but leaves its durable
sync to a later sync/1, so one sync can cover a batch of writes (group
commit). Absent, or sync: true, the write is durable on return.
Callbacks
@callback clear_all(ref :: ref()) :: :ok
Removes all entries.
@callback close(ref :: ref()) :: :ok
Closes the registry storage. Implementations MUST flush any pending writes before returning.
Returns true when key is present (and not expired).
Returns all entries as a list. The shape mirrors the existing
:ets.tab2list/1 output: 2-tuples for entries without TTL and
3-tuples for entries with TTL. Expired entries are filtered.
Folds fun over all entries with initial accumulator acc.
Returns the value stored under key, or nil if the key is missing
or expired.
Inserts value under key. Returns :ok once the write is durable
for the backend's durability model (synchronous for DETS, in-memory
for ETS).
@callback insert(ref :: ref(), key :: term(), value :: term(), opts :: insert_opts()) :: :ok | {:error, term()}
Inserts value under key with options.
Supported opts:
:ttl— milliseconds until the entry is considered expired. Stored as{key, value, expire_ms}; reads filter expired entries.
@callback insert_many(ref :: ref(), items :: [{term(), term(), insert_opts()}]) :: :ok | {:error, term()}
Optional: inserts a batch of {key, value, opts} items with a single
write, so concurrent readers never observe a partially applied batch.
Backends that omit this callback get per-item inserts instead.
@callback insert_many( ref :: ref(), items :: [{term(), term(), insert_opts()}], write_opts :: write_opts() ) :: :ok | {:error, term()}
Optional: insert_many/2 taking write_opts(). A backend that implements
it together with sync/1 lets the registry group-commit: several writes
applied with sync: false, then one sync/1 that makes them all durable.
Returns the list of matches for match_expr. The shape matches the
current ProcessHub.Service.Storage.match/2 (a list of tuples, not a
list of lists).
Opens (and if necessary creates) the registry storage for the given hub.
opts is a backend-specific keyword list. Returns {:ok, ref} on
success or {:error, reason} on unrecoverable failure.
Returns every non-expired row held in the backend's durable medium, as
{key, value} pairs, without inserting into, mutating, or otherwise affecting
the backend's live in-memory view.
Backends without a durable medium return {:ok, []}. A backend whose durable
medium is unreadable returns {:error, reason}; callers MUST treat an error as
"no candidates" rather than as an empty durable set, so a transient read
failure is never mistaken for "everything was deliberately removed".
Safe to call at any time on a running hub; it MUST NOT block mutations for longer than a single fold.
Optional: a backend that omits it is treated as having no durable medium, so backends written against earlier releases keep working.
Part of the experimental :auto_recovery feature; may change in future
releases.
Removes key.
@callback remove(ref :: ref(), key :: term(), write_opts :: write_opts()) :: :ok | {:error, term()}
Optional: remove/2 taking write_opts(); see insert_many/3.
Optional: makes every write applied with sync: false durable. Backends
without a durable medium need not implement it.