lc_ets_utils (faber_neuroevolution v1.2.4)

View Source

Shared ETS utilities for Liquid Conglomerate Silos.

Provides a consistent pattern for silos that need persistent collections: Competitive Silo: opponents, matches, elo_ratings Social Silo: reputations, coalitions, interactions Cultural Silo: innovations, traditions, memes Communication Silo: vocabulary, dialects, messages

Usage Pattern

In init/1, create tables for your silo:

EtsTables = lc_ets_utils:create_tables(competitive, Realm, TableSpecs)

In normal operation, use insert/lookup/delete:

lc_ets_utils:insert(Table, Key, Value) {ok, Data} = lc_ets_utils:lookup(Table, Key)

Cleanup when silo terminates:

lc_ets_utils:delete_tables(EtsTables)

Time-Based Operations

All entries are timestamped automatically for: Age-based pruning (remove stale entries) Recency queries (get most recent N entries) Decay calculations (reduce values over time)

Summary

Functions

Get all entries as a list of {Key, Value, Timestamp} tuples.

Get all keys in the table.

Average a numeric field from all values.

Count entries in the table.

Create ETS tables for a silo with consistent naming.

Delete an entry by key.

Delete all ETS tables in the map.

Filter entries matching a predicate.

Fold over all entries.

Execute a function for each entry (side effects).

Get the N oldest entries.

Get the N most recent entries.

Insert a key-value pair with automatic timestamp.

Insert with explicit timestamp (for time-travel or replay).

Lookup a value by key. Returns {ok, Value} or not_found.

Lookup a value with its timestamp.

Find maximum value of a numeric field.

Find minimum value of a numeric field.

Remove entries older than MaxAgeMs milliseconds.

Remove oldest entries to keep table at MaxCount size.

Sum a numeric field from all values.

Generate consistent table name atom.

Update a value using a function.

Types

table_name/0

-type table_name() :: atom().

table_ref/0

-type table_ref() :: ets:tid() | atom().

table_spec/0

-type table_spec() :: {table_name(), [ets:table_type() | {atom(), term()}]}.

timestamped_entry/0

-type timestamped_entry() :: {Key :: term(), Value :: term(), Timestamp :: integer()}.

Functions

all(Table)

-spec all(Table :: table_ref()) -> [timestamped_entry()].

Get all entries as a list of {Key, Value, Timestamp} tuples.

all_keys(Table)

-spec all_keys(Table :: table_ref()) -> [term()].

Get all keys in the table.

avg_field(Table, FieldFn)

-spec avg_field(Table :: table_ref(), FieldFn :: fun((term()) -> number())) -> number() | undefined.

Average a numeric field from all values.

count(Table)

-spec count(Table :: table_ref()) -> non_neg_integer().

Count entries in the table.

create_tables(SiloType, Realm, TableSpecs)

-spec create_tables(SiloType :: atom(), Realm :: binary(), TableSpecs :: [table_spec()]) ->
                       #{table_name() => table_ref()}.

Create ETS tables for a silo with consistent naming.

Tables are named: {SiloType}_{Realm}_{TableName} Example: competitive_realm1_opponents

Returns a map of table_name => ets:tid().

delete(Table, Key)

-spec delete(Table :: table_ref(), Key :: term()) -> true.

Delete an entry by key.

delete_tables(Tables)

-spec delete_tables(Tables :: #{table_name() => table_ref()}) -> ok.

Delete all ETS tables in the map.

filter(Pred, Table)

-spec filter(Pred :: fun((timestamped_entry()) -> boolean()), Table :: table_ref()) ->
                [timestamped_entry()].

Filter entries matching a predicate.

fold(Fun, InitAcc, Table)

-spec fold(Fun :: fun((timestamped_entry(), Acc) -> Acc), InitAcc :: Acc, Table :: table_ref()) -> Acc
              when Acc :: term().

Fold over all entries.

foreach(Fun, Table)

-spec foreach(Fun :: fun((timestamped_entry()) -> any()), Table :: table_ref()) -> ok.

Execute a function for each entry (side effects).

get_oldest(Table, N)

-spec get_oldest(Table :: table_ref(), N :: pos_integer()) -> [timestamped_entry()].

Get the N oldest entries.

get_recent(Table, N)

-spec get_recent(Table :: table_ref(), N :: pos_integer()) -> [timestamped_entry()].

Get the N most recent entries.

insert(Table, Key, Value)

-spec insert(Table :: table_ref(), Key :: term(), Value :: term()) -> true.

Insert a key-value pair with automatic timestamp.

insert_with_timestamp(Table, Key, Value, Timestamp)

-spec insert_with_timestamp(Table :: table_ref(),
                            Key :: term(),
                            Value :: term(),
                            Timestamp :: integer()) ->
                               true.

Insert with explicit timestamp (for time-travel or replay).

lookup(Table, Key)

-spec lookup(Table :: table_ref(), Key :: term()) -> {ok, term()} | not_found.

Lookup a value by key. Returns {ok, Value} or not_found.

lookup_with_timestamp(Table, Key)

-spec lookup_with_timestamp(Table :: table_ref(), Key :: term()) -> {ok, term(), integer()} | not_found.

Lookup a value with its timestamp.

max_field(Table, FieldFn)

-spec max_field(Table :: table_ref(), FieldFn :: fun((term()) -> number())) -> number() | undefined.

Find maximum value of a numeric field.

min_field(Table, FieldFn)

-spec min_field(Table :: table_ref(), FieldFn :: fun((term()) -> number())) -> number() | undefined.

Find minimum value of a numeric field.

prune_by_age(Table, MaxAgeMs)

-spec prune_by_age(Table :: table_ref(), MaxAgeMs :: pos_integer()) -> non_neg_integer().

Remove entries older than MaxAgeMs milliseconds.

Returns the number of entries deleted.

prune_by_count(Table, MaxCount)

-spec prune_by_count(Table :: table_ref(), MaxCount :: pos_integer()) -> non_neg_integer().

Remove oldest entries to keep table at MaxCount size.

Returns the number of entries deleted.

sum_field(Table, FieldFn)

-spec sum_field(Table :: table_ref(), FieldFn :: fun((term()) -> number())) -> number().

Sum a numeric field from all values.

FieldFn extracts the numeric field from each value.

table_name(SiloType, Realm, TableName)

-spec table_name(SiloType :: atom(), Realm :: binary(), TableName :: atom()) -> atom().

Generate consistent table name atom.

update(Table, Key, UpdateFn)

-spec update(Table :: table_ref(), Key :: term(), UpdateFn :: fun((term()) -> term())) -> ok.

Update a value using a function.

UpdateFn(OldValue) -> NewValue If key doesn't exist, UpdateFn(undefined) is called.