LeanLmdb (lean_lmdb v0.2.0)
View SourceA lean, binary-first Elixir wrapper for LMDB.
Environments are shared by canonical path within one BEAM OS process. Opaque environment and immutable named-database handles may live across calls; transactions and cursors never do. Keys and values are raw binaries and read results are copied into BEAM-owned binaries.
Example
iex> {name, version} = LeanLmdb.native_version()
iex> {name, Version.parse!(version).major}
{"lean_lmdb", 0}
Summary
Types
An ordered operation accepted by write_batch/2.
The expected state accepted by compare_exchange/4.
The replacement accepted by compare_exchange/4.
LMDB synchronization behavior selected when an environment is opened.
Validated options accepted by open/2.
A stable public error reason.
An option accepted by scan/2.
Functions
Checks the LMDB reader table and clears slots left by terminated processes.
Atomically compares a key's current state and applies a replacement on match.
Creates a named binary database, or reopens it when it already exists.
Deletes key if present.
Gets the binary value for key.
Returns deterministic lifecycle information for an environment or database.
Returns the tuple {"lean_lmdb", version} without accessing LMDB or the filesystem.
Opens an LMDB environment, sharing native state for its canonical path.
Opens an existing named binary database.
Stores value under key, overwriting any prior value.
Returns process-local registry counts and prunes stale weak entries.
Returns one bounded page of binary key/value pairs in ascending key order.
Forces the environment's pending data and metadata buffers to durable storage.
Applies an ordered list of puts and deletes atomically across named databases.
Types
@type batch_operation() :: {:put, LeanLmdb.Database.t(), binary(), binary()} | {:delete, LeanLmdb.Database.t(), binary()}
An ordered operation accepted by write_batch/2.
@type compare_expected() :: :missing | binary()
The expected state accepted by compare_exchange/4.
@type compare_replacement() :: :delete | {:put, binary()}
The replacement accepted by compare_exchange/4.
@type durability() :: :sync | :no_meta_sync | :no_sync
LMDB synchronization behavior selected when an environment is opened.
@type open_option() :: {:map_size, pos_integer()} | {:max_dbs, pos_integer()} | {:max_readers, pos_integer()} | {:read_only, boolean()} | {:create, boolean()} | {:durability, durability()} | {:fixed_map, boolean()}
Validated options accepted by open/2.
@type reason() :: :database_create_failed | :database_not_found | :database_open_failed | :environment_open_failed | :incompatible_environment_options | :invalid_database | :invalid_database_name | :invalid_environment | :invalid_key | :invalid_value | :io_error | :database_error | :map_full | :map_resized | :readers_full | :transaction_full | :out_of_memory | :invalid_environment_options | :invalid_batch | :batch_too_large | :mixed_environments | :invalid_expected | :invalid_replacement | :invalid_mode | :invalid_limit | :invalid_max_bytes | :row_too_large | :invalid_continuation | :stale_continuation | :invalid_path | :path_not_found | :read_only | :resource_id_exhausted | :transaction_failed | :sync_failed | {:invalid_option, atom()}
A stable public error reason.
@type scan_option() :: {:prefix, binary()} | {:from, binary() | nil} | {:to, binary() | nil} | {:from_inclusive, boolean()} | {:to_inclusive, boolean()} | {:limit, 1..10000} | {:max_bytes, 1..67_108_864} | {:continuation, binary() | nil}
An option accepted by scan/2.
Functions
@spec clear_stale_readers(LeanLmdb.Environment.t()) :: {:ok, non_neg_integer()} | {:error, reason()}
Checks the LMDB reader table and clears slots left by terminated processes.
Returns {:ok, cleared_count}. Active readers are never cleared. This is
backed by heed's Env::clear_stale_readers and may be called while the
environment is in use. Invalid handles and native failures return {:error, reason}.
@spec compare_exchange( LeanLmdb.Database.t(), binary(), compare_expected(), compare_replacement() ) :: :ok | {:conflict, :missing | binary()} | {:error, reason()}
Atomically compares a key's current state and applies a replacement on match.
:missing is distinct from an expected empty binary. A mismatch returns the
exact current state as {:conflict, :missing} or {:conflict, binary} and
never mutates the database. Missing deletes after a successful comparison are
idempotent. A match returns :ok; malformed arguments and native failures
return {:error, reason}. Conflict binaries are copied before return.
@spec create_database(LeanLmdb.Environment.t(), binary()) :: {:ok, LeanLmdb.Database.t()} | {:error, reason()}
Creates a named binary database, or reopens it when it already exists.
Names must contain 1..511 bytes of valid UTF-8 and may not contain NUL.
Returns {:ok, database} or {:error, reason}; read-only environments cannot
create databases. The immutable database handle retains its environment.
@spec delete(LeanLmdb.Database.t(), binary()) :: :ok | {:error, reason()}
Deletes key if present.
Deletion is idempotent: both present and missing keys return :ok. Validation,
read-only, and LMDB failures return {:error, reason}.
@spec get(LeanLmdb.Database.t(), binary()) :: {:ok, binary()} | :not_found | {:error, reason()}
Gets the binary value for key.
Returns {:ok, value} when present and :not_found when missing. Empty values
are therefore distinct from missing keys. Keys must be non-empty binaries no
larger than LMDB's runtime maximum key size. Native read failures return
{:error, reason}. The value is copied and no transaction or zero-copy view
escapes the call.
@spec info(LeanLmdb.Environment.t() | LeanLmdb.Database.t()) :: map() | {:error, :invalid_environment}
Returns deterministic lifecycle information for an environment or database.
Environment maps contain :resource_id, canonical :path, :map_size,
:max_dbs, :max_readers, :read_only, :durability, and :fixed_map;
database maps additionally contain :name. Invalid handles return
{:error, :invalid_environment}.
Returns the tuple {"lean_lmdb", version} without accessing LMDB or the filesystem.
@spec open(Path.t(), [open_option()]) :: {:ok, LeanLmdb.Environment.t()} | {:error, reason()}
Opens an LMDB environment, sharing native state for its canonical path.
The path is canonicalized after optional creation, so relative components and
symlinks resolve to the same identity. Defaults are a 64 MiB map, 16 named
databases, 126 readers, writable access, create: true, durability: :sync,
and fixed_map: false.
map_size must be between 1 MiB and 1 TiB and divisible by the operating
system page size; max_dbs is limited to 1..1024 and max_readers to
1..4096. A read-only environment cannot be created.
durability: :sync uses LMDB's fully synchronized default. :no_meta_sync
preserves database integrity but a system crash may undo the latest committed
transaction. :no_sync omits commit-time buffer flushes; a system crash can
lose transactions and, on a filesystem that reorders writes, can corrupt the
derived database. Call sync/1 to force pending buffers to durable storage.
fixed_map: true enables experimental MDB_FIXEDMAP. It can fail when the
recorded virtual address is unavailable and every process opening that
environment must use compatible settings. It is never enabled implicitly.
Repeats must use the same effective map size, limits, read mode, durability,
and fixed-map setting; create only controls path/open existence behavior.
Returns {:ok, environment} or {:error, reason}. The map never grows
automatically.
@spec open_database(LeanLmdb.Environment.t(), binary()) :: {:ok, LeanLmdb.Database.t()} | {:error, reason()}
Opens an existing named binary database.
Names follow the same UTF-8, length, and NUL restrictions as
create_database/2. Returns {:ok, database}, {:error, :database_not_found}, or another documented lifecycle error.
@spec put(LeanLmdb.Database.t(), binary(), binary()) :: :ok | {:error, reason()}
Stores value under key, overwriting any prior value.
Keys and values are used as raw binaries; no serialization is performed.
Returns :ok after commit or {:error, reason} without a partial commit.
@spec registry_info() :: %{ live: non_neg_integer(), stale: non_neg_integer(), total: non_neg_integer() }
Returns process-local registry counts and prunes stale weak entries.
This exposes counts only; it never reveals native pointers. It is intended for
deterministic lifecycle diagnostics and tests. The returned map always has
non-negative :live, :stale, and :total counts.
@spec scan(LeanLmdb.Database.t(), [scan_option()]) :: {:ok, [{binary(), binary()}], :done | binary()} | {:error, reason()}
Returns one bounded page of binary key/value pairs in ascending key order.
A scan is either a prefix scan (prefix: binary) or an explicit range scan.
Range endpoints default to nil; the lower endpoint is inclusive and the
upper endpoint exclusive by default. Prefix cannot be mixed with from, to,
or the inclusivity options. Prefixes and endpoints are at most 511 bytes. limit defaults to 100 (maximum 10,000) and
max_bytes defaults to 1 MiB (maximum 64 MiB), counting key plus value bytes.
The third result element is :done or an opaque continuation binary. Pass the
continuation with the same database and bounds to resume exclusively after
the last emitted key. Page limits may change while resuming. If the
first eligible row exceeds max_bytes, the call returns {:error, :row_too_large} and no rows, making the output byte budget a hard bound. Invalid options/tokens and
native read failures also return {:error, reason}. Pages do not share a
snapshot and all row/token bytes are copied before the call returns.
@spec sync(LeanLmdb.Environment.t()) :: :ok | {:error, reason()}
Forces the environment's pending data and metadata buffers to durable storage.
This calls LMDB's forced mdb_env_sync, even when the environment was opened
with durability: :no_sync or :no_meta_sync. It is intended for explicit
group-commit schedules such as a supervised timer. Writes can continue from
other processes while the dirty-I/O call runs; on return, LMDB reports that
all commits visible to that synchronization point have been flushed.
Returns :ok or {:error, reason}. Read-only and invalid handles are rejected.
@spec write_batch(LeanLmdb.Environment.t(), [batch_operation()]) :: :ok | {:error, reason()}
Applies an ordered list of puts and deletes atomically across named databases.
Every database must belong to exactly the supplied environment. The complete
list is validated before one write transaction is opened, operations are
applied in list order, and missing deletes are idempotent. Empty batches are
valid no-ops. A batch is limited to 10,000 operations and 64 MiB of aggregate
key and value bytes. Returns :ok only after commit; validation, mixed
environments, read-only access, and LMDB failures return {:error, reason}
with the transaction aborted.