kura_ets
ETS backend for kura — an in-memory, zero-dependency backend in the spirit of etso (Ecto's ETS adapter), for tests, caches, and small in-memory datasets.
Unlike the SQL backends (kura_postgres, kura_sqlite), this backend does
not compile queries to SQL. The dialect wraps the portable #kura_query{}
AST into an opaque {kura_ets, Plan} term, and the driver interprets that
plan directly against per-table ETS tables.
Usage
%% rebar.config
{deps, [kura, kura_ets]}.
%% sys.config
[{kura, [
{repos, #{
my_repo => #{
backend => kura_backend_ets
}
}}
]}].
Everything else is standard kura:
CS = kura_changeset:cast(my_user, #{}, #{id => 1, name => ~"alice"}, [id, name]),
{ok, Row} = kura_repo_worker:insert(my_repo, CS),
Q = kura_query:order_by(
kura_query:where(kura_query:from(my_user), {active, true}),
[{name, asc}]
),
{ok, Rows} = kura_repo_worker:all(my_repo, Q).
No migrations are needed (or possible): tables are created on first use and
data lives only as long as the pool. kura_ets_pool:reset(PoolName) clears
every table, which is handy between tests.
Modules
| Module | Role |
|---|---|
kura_backend_ets | Backend aggregator (backend => kura_backend_ets) |
kura_ets_pool | kura_pool impl; gen_server-owned table registry |
kura_ets_driver | kura_driver impl; executes plans |
kura_ets_dialect | kura_dialect impl; emits {kura_ets, Plan} terms |
kura_ets_query | Plan interpreter (filter / sort / project / aggregate) |
Supported
insert/insert_all, includingon_conflict(nothing,replace_all,{replace, Fields}) — conflict detection is on the primary key onlyget/get_by/one/all/exists/reload- Where conditions:
{F, V},=,!=,<,>,<=,>=,in,not_in, composite-columnin,between,like,ilike,is_nil,is_not_nil, nestedand/or/not order_by,limit,offset,distinct, field selection- Primary-key point lookups short-circuit to
ets:lookup/2(O(1); the storage key is the primary key), including composite keys - Aggregates:
count,sum,avg,min,max update/deleteby primary key,update_all/delete_all- Soft delete (
deleted_at), schema defaults, composite primary keys - Attribute-based multitenancy
- Sandbox checkout (
kura_sandbox)
Not supported
Queries using these return {error, {kura_ets_unsupported, _}}; raw SQL
returns {error, {kura_ets, raw_sql_unsupported}}:
- Joins,
group_by/having, CTEs,union/intersect/except, subqueries, fragments, window functions, full-textmatches, row locks, prefix-based multitenancy - Raw SQL — including migrations,
many_to_manyassociation persistence, and optimistic locking (kura builds SQL strings directly for those) - Transactions:
transaction/2runs the fun without atomicity — there is no rollback. The backend does not declare thetransactionscapability.
SQL semantics notes
- Rows store kura-dumped values; comparison values in queries are dumped through the schema's types before comparing, matching how a SQL client encodes parameters.
NULL(undefined/ missing) never satisfies a comparison; onlyis_nil/is_not_nilmatch it.- Duplicate primary keys produce a PG-shaped
23505unique-violation error, sokura_changesetconstraint mapping behaves as with SQL backends.
Development
rebar3 compile
rebar3 eunit
rebar3 fmt
kura is pulled from hex.pm. To develop against an unreleased local kura,
a _checkouts/kura symlink works, but note rebar3 then treats kura as a
project app and rebar3 eunit will also run kura's own test suite
(which needs a Postgres container) — scope with rebar3 eunit --app=kura_ets in that case.
Guides in docs/:
Looking for caching? That is application policy, not backend capability — see the sibling library kura_cache (keyed memoization with TTL, schema-keyed row cache, cluster invalidation hook).