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.

Summary

Types