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