Dala.State (dala v0.0.1)

Copy Markdown View Source

Persistent key-value store for app state.

Backed by :dets — Erlang's disk-based term storage, part of OTP stdlib. State survives app kills and restarts. Any Elixir term can be stored as a value; no serialisation step required.

When to use this vs. Ecto

  • Dala.State — app preferences, UI choices, small per-user settings. Think: selected theme, onboarding complete flag, last-opened tab, cached user ID. Designed for O(dozens) of keys, not O(thousands) of rows.

  • Your Ecto Repo — user records, structured data, anything you'd query, filter, or paginate. Use migrations and schemas for that.

Usage

# Store anything — atoms, maps, lists, nested structures.
Dala.State.put(:theme, :citrus)
Dala.State.put(:onboarded, true)
Dala.State.put(:last_position, %{lat: 43.7, lng: -79.4})

# Read back on next launch — returns `default` if not yet set.
Dala.State.get(:theme, :obsidian)   #=> :citrus
Dala.State.get(:missing_key, 0)     #=> 0

# Remove a key.
Dala.State.delete(:last_position)

Lifecycle

Started automatically by Dala.App.start/0 — no setup required. The backing file is stored at dala_DATA_DIR/dala_state.dets on device, or priv/repo/dala_state.dets in local dev (same directory as the SQLite DB).

Summary

Functions

Returns a specification to start this module under a supervisor.

Delete a key.

Read a persisted value.

Persist a key-value pair to disk.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

delete(key)

@spec delete(term()) :: :ok

Delete a key.

No-op if the key is absent. The deletion is synchronised to disk before this function returns.

Dala.State.delete(:theme)
Dala.State.get(:theme, :obsidian)   #=> :obsidian

get(key, default \\ nil)

@spec get(term(), term()) :: term()

Read a persisted value.

Returns default if the key has never been written. default is nil unless explicitly provided.

iex> Dala.State.get(:theme, :obsidian)
:obsidian

iex> Dala.State.put(:theme, :citrus)
iex> Dala.State.get(:theme, :obsidian)
:citrus

Reads go directly to the underlying :dets table without going through the GenServer, so they never queue behind in-flight writes.

put(key, value)

@spec put(term(), term()) :: :ok

Persist a key-value pair to disk.

Any Elixir term is accepted for both key and value. Backed by :dets (Erlang's disk-based term storage) with a sync after each write, so the value is on disk before this function returns and survives an immediate SIGKILL (Android OOM kill, iOS termination under memory pressure).

Dala.State.put(:theme, :citrus)
Dala.State.put(:onboarded, true)
Dala.State.put({:last_seen, :home}, DateTime.utc_now())
Dala.State.put(:prefs, %{font_size: 16, notifications: true})

Calling put/2 with an existing key overwrites the previous value.