View Source ProcessHub.Service.Storage.DurableEts (ProcessHub v0.6.0)
Hybrid registry storage. Selected via
registry_backend: {:durable_ets, opts} on ProcessHub.t().
ETS is the source-of-truth for reads and writes; every mutation is
mirrored to a DETS file with :dets.sync/1 before returning, so
durability is no weaker than the ProcessHub.Service.Storage.Dets
backend. On open/2 the DETS file is replayed into ETS so reads are
immediately authoritative.
When to use
Pick this backend when you want the read latency of the :ets
backend (every child_lookup/2, process_list/2, and
start_children check_existing lookup is a single
:ets.lookup) and restart-survival of the {:dets, _} backend.
File location
Identical to the :dets backend. Default
priv/process_hub/<hub_id>/registry.dets; override with the :path
option:
registry_backend: {:durable_ets, path: "/var/lib/myapp/hub.dets"}The format on disk is a plain DETS file — switching a hub between
{:dets, _} and {:durable_ets, _} against the same path picks up
the existing rows.
Recovery on corruption
Same rotation behaviour as the DETS backend: on a corrupt file the
original is moved aside as <path>.corrupt-<system_monotonic>,
telemetry [:process_hub, :registry, :backend_corrupt] is emitted,
and a fresh empty DETS file is opened. The ETS table is empty in
this case (the rows were not loadable).
Crash semantics
Between the ETS write and the :dets.sync/1 return, the row is in
memory but not durable. On restart, the ETS table is rebuilt from
the DETS file — an inflight write is lost. Identical to the DETS
backend's existing crash window.
On a DETS-write error (e.g. underlying volume becomes read-only),
the just-inserted ETS row is rolled back via :ets.delete/2 so
observers see consistent state and the call returns
{:error, reason}.
TTL
Same as the DETS backend. Entries inserted with :ttl are stored
as {key, value, expire_ms} in both ETS and DETS; reads filter
expired entries on the way out.