noxu/lib.rs
1// Copyright (C) 2024-2025 Greg Burd. Licensed under either of the
2// Apache License, Version 2.0 or the MIT license, at your option.
3// See LICENSE-APACHE and LICENSE-MIT at the root of this repository.
4// SPDX-License-Identifier: Apache-2.0 OR MIT
5
6//! # Noxu DB — umbrella crate
7//!
8//! **`noxu`** is the single crate users depend on to get the full
9//! Noxu DB engine. It re-exports the public API of all component crates
10//! behind a single name and version so you write only:
11//!
12//! ```toml
13//! [dependencies]
14//! noxu = "7"
15//! ```
16//!
17//! ## Quick-start
18//!
19//! ```no_run
20//! use noxu::{DatabaseConfig, Environment, EnvironmentConfig};
21//! use std::path::PathBuf;
22//!
23//! # fn main() -> noxu::Result<()> {
24//! let env = Environment::open(
25//! EnvironmentConfig::new(PathBuf::from("/tmp/mydb"))
26//! .with_allow_create(true)
27//! .with_transactional(true),
28//! )?;
29//! let db_config = DatabaseConfig::new()
30//! .with_allow_create(true)
31//! .with_transactional(true);
32//! let db = env.open_database(None, "kv", &db_config)?;
33//! let txn = env.begin_transaction(None)?;
34//! db.put_in(&txn, b"hello", b"world")?;
35//! txn.commit()?;
36//!
37//! // Reads return `Result<Option<Bytes>>`.
38//! if let Some(value) = db.get(b"hello")? {
39//! assert_eq!(value.as_ref(), b"world");
40//! }
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! ## Feature flags
46//!
47//! | Feature | Default | What it enables |
48//! |---|---|---|
49//! | `collections` | yes | [`collections`] module — `StoredMap`, `StoredSet`, `StoredList` |
50//! | `persist` | yes | [`persist`] module — `#[derive(Entity)]`, `PrimaryIndex`, `EntityStore` |
51//! | `xa` | yes | [`xa`] module — XA two-phase-commit (`XaEnvironment`) |
52//! | `replication` | no | `replication` module — master-replica HA, elections |
53//! | `replication-tls-rustls` | no | TLS for replication via pure-Rust `rustls` |
54//! | `replication-tls-native` | no | TLS for replication via OS/OpenSSL |
55//! | `observability` | no | `observe` module — `tracing` + `metrics` glue |
56//!
57//! ## Using Noxu from async code
58//!
59//! **Noxu is synchronous by design.** Every operation (`get`, `put`,
60//! `commit`, cursor navigation, `Environment::open`) is blocking: it does
61//! real disk I/O, acquires locks, and may park the calling thread. There is
62//! no `async` API and none is planned — the engine uses explicit threads and
63//! blocking I/O throughout (only the optional `replication` feature's
64//! networking uses `tokio` internally).
65//!
66//! If you call Noxu from inside a `tokio` (or other async) runtime, do **not**
67//! call it directly on an async worker thread — a blocking call there stalls
68//! every other task sharing that worker. Instead, move the work onto a
69//! blocking thread:
70//!
71//! ```ignore
72//! # async fn example(env: std::sync::Arc<noxu::Environment>) -> Result<(), Box<dyn std::error::Error>> {
73//! // `env` is Send + Sync; clone the Arc into the blocking task.
74//! let value = tokio::task::spawn_blocking(move || {
75//! let db_cfg = noxu::DatabaseConfig::new().with_allow_create(true);
76//! let db = env.open_database(None, "users", &db_cfg)?;
77//! db.put(b"k", b"v")?;
78//! db.get(b"k")
79//! })
80//! .await??; // first `?`: JoinError; second `?`: NoxuError
81//! # let _ = value;
82//! # Ok(())
83//! # }
84//! ```
85//!
86//! Guidelines:
87//!
88//! - Wrap each unit of Noxu work in `tokio::task::spawn_blocking` (or a
89//! dedicated blocking thread pool), not the async path.
90//! - **Never hold a [`Transaction`] (or an open [`Cursor`]) across an
91//! `.await`.** A transaction holds locks; suspending the task while it is
92//! open can block other writers indefinitely and the borrow on the
93//! transaction would also prevent the future from being `Send`. Open,
94//! use, and commit/abort a transaction entirely within one
95//! `spawn_blocking` closure.
96//! - `Environment` is `Send + Sync`, so share it across tasks via
97//! `Arc<Environment>` and open per-task databases/transactions inside the
98//! blocking closure.
99//!
100//! ## Derive macros
101//!
102//! With the `persist` feature (on by default) the derive macros
103//! `Entity`, `PrimaryKey`, and `SecondaryKey` are available directly
104//! through this crate:
105//!
106//! ```no_run
107//! use noxu::persist::{Entity, SecondaryKey};
108//!
109//! #[derive(Clone, Entity, SecondaryKey)]
110//! struct User {
111//! #[primary_key]
112//! id: u64,
113//! #[secondary_key(name = "by_email", relate = OneToOne)]
114//! email: String,
115//! }
116//! ```
117
118// Re-export the entire core public API at the crate root.
119pub use noxu_db::*;
120
121/// Binding helpers: tuple encoding, entry views, serial encoding.
122pub mod bind {
123 pub use noxu_bind::*;
124}
125
126/// Iterator-based collection views (`StoredMap`, `StoredSet`, `StoredList`).
127#[cfg(feature = "collections")]
128pub mod collections {
129 pub use noxu_collections::*;
130}
131
132/// Trait-based entity persistence (DPL): `Entity`, `PrimaryKey`,
133/// `PrimaryIndex`, `EntityStore`, and the derive macros.
134///
135/// The derive macros (`#[derive(Entity)]`, `#[derive(PrimaryKey)]`,
136/// `#[derive(SecondaryKey)]`) are re-exported here so that the generated
137/// code — which references `::noxu::persist::…` paths — resolves
138/// correctly when the user only depends on the `noxu` umbrella crate.
139#[cfg(feature = "persist")]
140pub mod persist {
141 pub use noxu_persist::*;
142 // Re-export the derive macros so `use noxu::persist::Entity;` brings
143 // both the trait AND the derive macro into scope.
144 pub use noxu_persist_derive::{Entity, PrimaryKey, SecondaryKey};
145}
146
147/// XA distributed transactions (X/Open XA two-phase commit).
148#[cfg(feature = "xa")]
149pub mod xa {
150 pub use noxu_xa::*;
151}
152
153/// Master-replica high-availability replication.
154#[cfg(feature = "replication")]
155pub mod replication {
156 pub use noxu_rep::*;
157}
158
159/// Optional observability integration (`tracing` + `metrics` + OpenTelemetry).
160#[cfg(feature = "observability")]
161pub mod observe {
162 pub use noxu_observe::*;
163}