Storage backend for EDA's caches.
EDA's caches are split in two: this behaviour owns where entities are stored, while
EDA.Cache.Guild and friends own which ones are stored and how many — admission
policy (EDA.Cache.Policy), size limits and eviction (EDA.Cache.Evictor), and
telemetry.
That split is deliberate. A backend only has to answer "where does this live"; it never reimplements admission filtering or memory bounds, because those sit above it. Every adapter — including one you write yourself — inherits them for free.
Configuration
config :eda, cache_adapter: EDA.Cache.Adapter.ETS # default
config :eda, cache_adapter: EDA.Cache.Adapter.NoOp # store nothingThe adapter is resolved once at startup by EDA.Cache.Config and read from
:persistent_term, so lookups on the hot path cost nothing.
Key shapes
Caches use one of two key shapes, and an adapter must support both:
- a flat binary id — guilds and users;
- a composite
{guild_id, id}tuple — channels, members, roles, presences and voice states.match_prefix/2anddelete_prefix/2exist to serve "everything in this guild" without scanning the whole table.
Channels and roles additionally keep a secondary index table mapping a bare id back to
its guild, so they can be looked up without knowing the guild. An index is just another
table from the adapter's point of view — put/3 and get/2 serve it.
Writing an adapter
Implement every callback. init/2 is called once per table at startup; the rest must be
safe to call from any process, since EDA reads caches directly from the caller rather
than through a GenServer.
defmodule MyApp.RedisCache do
@behaviour EDA.Cache.Adapter
# ...
end
Summary
Types
A flat id or a {guild_id, id} tuple.
The logical table name, e.g. :eda_guilds.
A cached entity, as a raw string-keyed map, or an index value.
Callbacks
Every value in the table.
How many entries the table holds.
Removes one key. Removing an absent key is not an error.
Removes every entry whose key is {prefix, _}, returning the second element of each
key removed.
Fetches one value, or nil.
Prepares a table. Called once per table at startup.
Every value whose key is {prefix, _}.
Stores a value, replacing any existing one.
Types
Callbacks
Every value in the table.
@callback count(table()) :: non_neg_integer()
How many entries the table holds.
Removes one key. Removing an absent key is not an error.
Removes every entry whose key is {prefix, _}, returning the second element of each
key removed.
The return value lets a cache clean up its secondary index without a second scan.
Fetches one value, or nil.
Prepares a table. Called once per table at startup.
Every value whose key is {prefix, _}.
Only meaningful for composite-key tables; a flat-key table may return [].
Stores a value, replacing any existing one.
Functions
@spec current() :: module()
The configured adapter module.
Resolved at startup into :persistent_term; falls back to EDA.Cache.Adapter.ETS.