ETS-backed cache of the CMS settings, loaded once at boot and refreshed on change so reads are
lock-free on every request (mirrors MishkaCmsCore.Runtime.States.SiteState). The durable source
of truth is MishkaCmsCore.Runtime.Setting; application code should go through the
MishkaCmsCore.Settings facade rather than this module directly.
Settings are multitenant (see MishkaCmsCore.Runtime.Setting), so each entry is keyed by
{site_id, key} — site_id = nil is the GLOBAL value, a site_id is that site's override. A read
for a site resolves site value → global value → default, all from ETS with no GenServer hop.
Summary
Functions
All GLOBAL settings (site_id nil) as %{key => value_map} — used for default seeding.
Returns a specification to start this module under a supervisor.
Drop a setting from the cache.
Lock-free read of a setting's stored map for site_id (nil = global). A per-site lookup that misses
falls back to the global value, then to default.
Lock-free read of a site's OWN stored map, with no fallback to the global value: default when the
site holds none.
Upsert a setting into the cache directly (test/seed helper; the façade uses refresh_key/2).
Reload every setting from the database into ETS.
Reconcile one {site_id, key} entry with the database (called by the facade after a durable write).
Re-reading inside the serialized GenServer makes the cache reflect DB-commit order, not caller
arrival order — so concurrent writes to the same key converge on the committed value, and a removed
row drops from the cache.
Puts the cache back to a snapshot/0 (test helper). It reads no database, so it works from an
on_exit, which a refresh/0 there does not: that one runs before the test's transaction rolls
back, and loads the test's own writes back into the cache.
Everything the cache holds now, for restore/1 (test helper).
Functions
All GLOBAL settings (site_id nil) as %{key => value_map} — used for default seeding.
Returns a specification to start this module under a supervisor.
See Supervisor.
Drop a setting from the cache.
Lock-free read of a setting's stored map for site_id (nil = global). A per-site lookup that misses
falls back to the global value, then to default.
Lock-free read of a site's OWN stored map, with no fallback to the global value: default when the
site holds none.
Upsert a setting into the cache directly (test/seed helper; the façade uses refresh_key/2).
@spec refresh() :: :ok
Reload every setting from the database into ETS.
Reconcile one {site_id, key} entry with the database (called by the facade after a durable write).
Re-reading inside the serialized GenServer makes the cache reflect DB-commit order, not caller
arrival order — so concurrent writes to the same key converge on the committed value, and a removed
row drops from the cache.
Puts the cache back to a snapshot/0 (test helper). It reads no database, so it works from an
on_exit, which a refresh/0 there does not: that one runs before the test's transaction rolls
back, and loads the test's own writes back into the cache.
Everything the cache holds now, for restore/1 (test helper).
snapshot = SettingsState.snapshot()
on_exit(fn -> SettingsState.restore(snapshot) end)