armdb 0.11.2

sharded bitcask key-value storage optimized for NVMe
Documentation
//! Integration with the armour ecosystem (feature `armour`).
//!
//! Provides multi-tree database management, schema-versioned migrations,
//! and a binary RPC server compatible with armour-rpc clients.
//!
//! # Components
//!
//! - [`Db`] — manages a directory of named collections with persistent
//!   metadata ([`DbInfo`]) and sequential ID generation.
//! - [`TreeMeta`] — static descriptor for a collection (name, key scheme, type, version).
//! - [`Db::open_typed_tree`] / [`Db::open_typed_map`] /
//!   [`Db::open_zero_tree`] / [`Db::open_zero_map`] —
//!   open a tree or map with automatic migration when the stored schema version
//!   differs from [`TreeMeta::version`].
//! - [`Db::inspector`] — borrowed in-process read-only diagnostic API over
//!   every collection opened through this [`Db`]. Does not require or alter RPC.
//! - [`Inspector`] — discovery, schema, raw key/value reads, counts, and bounded
//!   scans. Authentication, redaction, JSON, and audit logging stay with the
//!   application.
//! - [`RpcHandler`] — trait for handling binary RPC requests per collection.
//!   Every collection opened through [`Db`] (`open_typed_tree`, `open_zero_map`,
//!   `open_var_typed_tree`, `open_lsm_tree`, …) is registered on both the RPC
//!   and Inspection surfaces automatically — no handler struct to write.
//!   `RpcHandler` itself stays public so an application can still hand-write a
//!   custom implementation, e.g. for a collection opened outside this `Db`.
//! - [`TreeMap`] — `Arc<HashMap<u64, Arc<dyn RpcHandler>>>` routing table
//!   (key = `xxh3(name)`), built from every registered handler via
//!   [`Db::build_tree_map`].
//!
//! # Read-only Inspector
//!
//! [`Db::inspector`] returns a borrowed [`Inspector`] tied to the owning `Db`.
//! Only collections opened through that `Db` are visible; directly opened
//! trees and maps are not registered.
//!
//! **Discovery** — [`Inspector::collections`] lists every registered collection
//! sorted by name with [`InspectionCollection`] metadata: [`InspectionSchema`]
//! (version, [`Typ`](armour_core::Typ), [`KeyScheme`](armour_core::KeyScheme),
//! key size, [`InspectionEncoding`](crate::InspectionEncoding)), storage class
//! ([`StorageClass`](armour_core::StorageClass)), optional cheap count,
//! [`ScanCapability`], and [`IterationDirection`] when ordered.
//!
//! **Value encoding** — [`InspectionEncoding::Rapira`] means value bytes are
//! accepted by generic `DynValue` decoding for the collection [`Typ`](armour_core::Typ).
//! Zero collections may report `Rapira` on little-endian targets when the computed
//! fixed `Typ` width equals the stored value width; otherwise they report
//! [`InspectionEncoding::RawLayout`]. Keys are not part of this contract — they
//! are exposed as raw bytes via each collection's [`KeyScheme`](armour_core::KeyScheme).
//! [`InspectionEncoding::Opaque`] declares no generic decoder contract.
//!
//! ```no_run
//! # use armdb::armour::Inspector;
//! # fn example(inspector: &Inspector<'_>, name: &str, key: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
//! let schema = inspector.schema(name)?;
//! let entry = inspector.get(name, key)?.expect("present");
//! let value = armour_core::dyn_value::decode(&schema.typ, &entry.value)?;
//! let _ = value;
//! # Ok(())
//! # }
//! ```
//!
//! This does **not** promise that `rapira::deserialize::<ConcreteType>` succeeds.
//! Compatible Zero layouts may not implement `Rapira` at all, and DynValue decoding
//! intentionally differs from typed Rapira for some values (for example non-finite floats).
//!
//! **Counts** — [`CountMode::Current`] uses the handler's O(1) live-key counter
//! when available; [`CountMode::Exact`] performs a strict key-only scan that
//! includes unreadable values and fails on storage errors (Var/LSM paths
//! propagate failures instead of returning partial results).
//!
//! **Ordered scans** — [`Inspector::range`] and [`Inspector::prefix`] honor the
//! collection's byte order and configured direction. Pass the previous page's
//! `next_key` as `after` to continue in ascending or reversed order. Pagination
//! uses a one-row lookahead so `next_key` is set only when another row exists.
//! Pages are not a cross-shard or cross-page point-in-time snapshot.
//!
//! **Unordered snapshot** — [`Inspector::snapshot_unordered`] walks a
//! non-iterable Map in per-shard unspecified order; it is not a global snapshot.
//!
//! **Map iterability** — whether an iterable Map supports ordered scans is
//! decided at open time (`iterable(true)`); non-iterable Maps expose
//! [`ScanCapability::UnorderedSnapshot`] instead.
//!
//! Inspector exposes no mutation methods. See [`Db::inspector`] for
//! `compile_fail` boundary examples.
//!
//! # Quick start
//!
//! ```ignore
//! use armdb::armour::Db;
//! use armdb::{Config, NoHook, RapiraCodec};
//!
//! let db = Db::open("data/myapp")?;
//! // Opening a collection through `db` registers it on the RPC and
//! // Inspection surfaces — no handler to write or register by hand.
//! let tree = db.open_typed_tree::<User, RapiraCodec, _>(
//!     Config::balanced().build(), NoHook, &[])?;
//!
//! // Start the RPC server. Each `listen_*` call builds its own routing table
//! // from every collection opened so far.
//! db.listen_tcp("127.0.0.1:9000");
//! db.listen_uds("/tmp/myapp.sock");
//! ```
//!
//! # RPC protocol
//!
//! Length-delimited frames over TCP or Unix socket. Each request carries an
//! opcode, a collection hashname (`xxh3` of the collection name), and an
//! operation-specific payload. See [`rpc`] module for codec details.
//!
//! Graceful shutdown: Ctrl-C sends a broadcast via `async_broadcast`;
//! all accept loops and active connections terminate.

pub mod collection;
pub mod db;
#[cfg(feature = "rpc")]
pub mod handler;
#[cfg(not(feature = "rpc"))]
pub(crate) mod handler;
pub mod inspection;
pub mod migration;
#[cfg(feature = "rpc")]
pub mod rpc;
pub mod seq;
pub(crate) mod typ_width;
#[cfg(feature = "rpc")]
pub mod typed_client;

pub use crate::{CollectionMeta, Key, TreeMeta};
pub use crate::{
    FormatAction, FormatMigration, FormatMigrationPolicy, FormatMigrationReport, FormatStepFn,
};
pub use collection::Collection;
pub use db::{CollectionInfo, Db, DbBuilder, DbInfo, TYP_HASH_MIGRATING, WorkerIntervals};
#[cfg(feature = "rpc")]
pub use handler::RpcHandler;
pub use inspection::{
    CountMode, InspectionCollection, InspectionEncoding, InspectionEntry, InspectionError,
    InspectionOperation, InspectionPage, InspectionSchema, Inspector, IterationDirection,
    ScanCapability,
};
pub use migration::{TypedMigration, TypedMigrationFn};
#[cfg(feature = "rpc")]
pub use rpc::TreeMap;
pub use seq::SeqGen;
#[cfg(feature = "rpc")]
pub use typed_client::TypedRpcClient;