shelf/bag

Types

An open persistent bag table with typed keys and values.

pub opaque type PBag(k, v)

Values

pub fn close(table: PBag(k, v)) -> Result(Nil, shelf.ShelfError)

Close the table, saving all data to disk.

On Ok(Nil), the handle must not be used again. If the final save fails with a retryable persistence error, close() returns Error(...) and leaves the table open so the caller can retry. If close fails terminally, Shelf still releases resources and future operations on the handle return Error(TableClosed).

pub fn delete_all(
  from table: PBag(k, v),
) -> Result(Nil, shelf.ShelfError)

Delete all entries from the table.

The table remains open and usable after this call — only the data is removed. To release the table entirely, use close.

pub fn delete_key(
  from table: PBag(k, v),
  key key: k,
) -> Result(Nil, shelf.ShelfError)

Delete all values for the given key.

pub fn delete_object(
  from table: PBag(k, v),
  key key: k,
  value value: v,
) -> Result(Nil, shelf.ShelfError)

Delete a specific key-value pair.

Only the exact matching pair is removed. Other values for the same key are preserved.

pub fn fold(
  over table: PBag(k, v),
  from initial: acc,
  with fun: fn(acc, k, v) -> acc,
) -> Result(acc, shelf.ShelfError)

Fold over all entries. Order is unspecified.

pub fn insert(
  into table: PBag(k, v),
  key key: k,
  value value: v,
) -> Result(Nil, shelf.ShelfError)

Insert a key-value pair. Duplicate key-value pairs are ignored.

pub fn insert_list(
  into table: PBag(k, v),
  entries entries: List(#(k, v)),
) -> Result(Nil, shelf.ShelfError)

Insert multiple key-value pairs.

pub fn lookup(
  from table: PBag(k, v),
  key key: k,
) -> Result(List(v), shelf.ShelfError)

Look up all values for a key.

Returns Error(NotFound) if the key does not exist.

pub fn member(
  of table: PBag(k, v),
  key key: k,
) -> Result(Bool, shelf.ShelfError)

Check if a key exists without returning the values.

pub fn open(
  name name: String,
  path path: String,
  base_directory base_directory: String,
  key key_decoder: decode.Decoder(k),
  value value_decoder: decode.Decoder(v),
) -> Result(PBag(k, v), shelf.ShelfError)

Open a persistent bag table with defaults (WriteBack mode).

let assert Ok(table) =
  bag.open(name: "tags", path: "tags.dets",
    base_directory: "/app/data",
    key: decode.string, value: decode.string)
pub fn open_config(
  config config: shelf.Config,
  key key_decoder: decode.Decoder(k),
  value value_decoder: decode.Decoder(v),
) -> Result(PBag(k, v), shelf.ShelfError)

Open a persistent bag table with full configuration.

If the DETS file exists, its contents are loaded into a fresh ETS table after validating each entry through the provided decoders. If no file exists, both tables start empty.

The DETS file path is validated against the configured base directory.

let config =
  shelf.config(name: "tags", path: "tags.dets",
    base_directory: "/app/data")
  |> shelf.write_mode(shelf.WriteThrough)
let assert Ok(table) =
  bag.open_config(config, key: decode.string, value: decode.string)
pub fn reload(table: PBag(k, v)) -> Result(Nil, shelf.ShelfError)

Discard unsaved ETS changes and reload from DETS.

Clears the ETS table, re-reads all DETS entries, validates them through the stored decoders, and loads valid entries into ETS. Only useful in WriteBack mode — in WriteThrough mode, ETS and DETS are always in sync.

pub fn save(table: PBag(k, v)) -> Result(Nil, shelf.ShelfError)

Snapshot the current ETS contents to DETS.

Uses an atomic save strategy: data is written to a temporary file first, then atomically renamed over the original DETS file. This prevents data loss if the process is killed mid-save.

pub fn size(
  of table: PBag(k, v),
) -> Result(Int, shelf.ShelfError)

Return the number of entries in the table.

pub fn sync(table: PBag(k, v)) -> Result(Nil, shelf.ShelfError)

Flush the DETS write buffer to the OS.

DETS buffers writes internally. This forces them to be written to the underlying filesystem. Most useful in WriteThrough mode when you want to guarantee durability.

pub fn to_list(
  from table: PBag(k, v),
) -> Result(List(#(k, v)), shelf.ShelfError)

Return all key-value pairs as a list.

Warning: loads entire table into memory.

pub fn with_table(
  name name: String,
  path path: String,
  base_directory base_directory: String,
  key key_decoder: decode.Decoder(k),
  value value_decoder: decode.Decoder(v),
  fun fun: fn(PBag(k, v)) -> Result(a, shelf.ShelfError),
) -> Result(a, shelf.ShelfError)

Use a table within a callback, ensuring it is closed afterward.

If the final save fails during close, with_table force-cleans the table to release resources. If the callback succeeded, the close error is returned; if both the callback and close fail, the callback error is preserved.

use table <- bag.with_table("tags", "tags.dets",
  base_directory: "/app/data",
  key: decode.string, value: decode.string)
bag.insert(table, "color", "red")
Search Document