Botica.Flags.Store (Botica v2.0.0)

Copy Markdown View Source

ETS-backed storage for Botica.Flags.Flag structs.

Architecture

  • The ETS table :botica_flags is :public and read_concurrency: true so reads are O(1) and lock-free, even under heavy concurrent load.
  • Writes go through the GenServer (put/1, delete/1) so that mutations are serialised and the table stays consistent.
  • The GenServer is also where flag lifecycle events (defined, enabled, disabled, rollout-changed) can be hooked in the future via telemetry.

Usage

In most cases you should not call this module directly — use the Botica.Flags facade instead. Direct access is allowed when you need the cheapest possible read and you're certain the Store is up:

iex> Botica.Flags.Store.get(:my_flag)
{:ok, %Botica.Flags.Flag{...}}

iex> Botica.Flags.Store.all()
[%Botica.Flags.Flag{...}, ...]

Summary

Functions

Direct ETS read of all flags. Returns a list (may be empty), sorted by updated_at descending so most recently touched flags appear first.

Returns a specification to start this module under a supervisor.

Total number of registered flags. Cheap ETS count.

Remove a flag from the registry.

Direct ETS read — no GenServer round-trip. Returns {:ok, flag} or :error.

GenServer-mediated write. Serialised to avoid race conditions between concurrent definitions / enable / disable / set calls.

Returns the underlying ETS table name. Useful in tests for clearing the registry between cases: Store.table() |> :ets.delete_all_objects().

Functions

all()

@spec all() :: [Botica.Flags.Flag.t()]

Direct ETS read of all flags. Returns a list (may be empty), sorted by updated_at descending so most recently touched flags appear first.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

count()

@spec count() :: non_neg_integer()

Total number of registered flags. Cheap ETS count.

delete(name)

@spec delete(atom()) :: :ok

Remove a flag from the registry.

get(name)

@spec get(atom()) :: {:ok, Botica.Flags.Flag.t()} | :error

Direct ETS read — no GenServer round-trip. Returns {:ok, flag} or :error.

put(flag)

@spec put(Botica.Flags.Flag.t()) :: :ok

GenServer-mediated write. Serialised to avoid race conditions between concurrent definitions / enable / disable / set calls.

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

table()

@spec table() :: :ets.tab()

Returns the underlying ETS table name. Useful in tests for clearing the registry between cases: Store.table() |> :ets.delete_all_objects().