walrus_rust/lib.rs
1//! # Walrus ðŸ¦
2//!
3//! A high-performance Write-Ahead Log (WAL) implementation in Rust designed for concurrent
4//! workloads with topic-based organization, configurable consistency models, and dual storage backends.
5//!
6//! ## Features
7//!
8//! - **High Performance**: Optimized for concurrent writes and reads
9//! - **Topic-based Organization**: Separate read/write streams per topic
10//! - **Configurable Consistency**: Choose between strict and relaxed consistency models
11//! - **Batched I/O**: Atomic batch append and read APIs (uses io_uring on Linux with FD backend)
12//! - **Dual Storage Backends**: FD backend with pread/pwrite (default) or mmap backend
13//! - **Persistent Read Offsets**: Read positions survive process restarts
14//! - **Namespace Isolation**: Separate WAL instances with per-key directories
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use walrus_rust::{Walrus, ReadConsistency};
20//!
21//! # fn main() -> std::io::Result<()> {
22//! // Create a new WAL instance
23//! let wal = Walrus::new()?;
24//!
25//! // Write data to a topic
26//! wal.append_for_topic("my-topic", b"Hello, Walrus!")?;
27//!
28//! // Read data from the topic (checkpoint=true consumes the entry)
29//! if let Some(entry) = wal.read_next("my-topic", true)? {
30//! println!("Read: {:?}", String::from_utf8_lossy(&entry.data));
31//! }
32//!
33//! // Peek at the next entry without consuming it (checkpoint=false)
34//! if let Some(entry) = wal.read_next("my-topic", false)? {
35//! println!("Peeking: {:?}", String::from_utf8_lossy(&entry.data));
36//! }
37//! # Ok(())
38//! # }
39//! ```
40//!
41//! ## Batch Operations
42//!
43//! Walrus supports efficient batch writes and reads. On Linux with the FD backend (default),
44//! batch operations automatically use io_uring for parallel I/O submission. On other platforms
45//! or with the mmap backend, batches fall back to sequential operations.
46//!
47//! **Limits:**
48//! - Maximum 2,000 entries per batch
49//! - Maximum ~10GB total payload per batch
50//!
51//! ```rust,no_run
52//! use walrus_rust::Walrus;
53//!
54//! # fn main() -> std::io::Result<()> {
55//! let wal = Walrus::new()?;
56//!
57//! // Atomic batch write (all-or-nothing)
58//! let batch = vec![
59//! b"entry 1".as_slice(),
60//! b"entry 2".as_slice(),
61//! b"entry 3".as_slice(),
62//! ];
63//! wal.batch_append_for_topic("events", &batch)?;
64//!
65//! // Batch read with byte limit (returns at least 1 entry if available)
66//! let max_bytes = 1024 * 1024; // 1MB
67//! let entries = wal.batch_read_for_topic("events", max_bytes, true)?;
68//! for entry in entries {
69//! println!("Read: {} bytes", entry.data.len());
70//! }
71//! # Ok(())
72//! # }
73//! ```
74//!
75//! ## Consistency Models
76//!
77//! Control the trade-off between durability and performance:
78//!
79//! ```rust,no_run
80//! use walrus_rust::{Walrus, ReadConsistency, FsyncSchedule};
81//!
82//! # fn main() -> std::io::Result<()> {
83//! // Strict consistency - every read checkpoint is persisted immediately
84//! let wal = Walrus::with_consistency(ReadConsistency::StrictlyAtOnce)?;
85//!
86//! // At-least-once delivery - persist every N reads (higher throughput)
87//! // This allows replaying up to N entries after a crash
88//! let wal = Walrus::with_consistency(
89//! ReadConsistency::AtLeastOnce { persist_every: 1000 }
90//! )?;
91//! # Ok(())
92//! # }
93//! ```
94//!
95//! ## Fsync Scheduling
96//!
97//! Configure when data is flushed to disk:
98//!
99//! ```rust,no_run
100//! use walrus_rust::{Walrus, ReadConsistency, FsyncSchedule};
101//!
102//! # fn main() -> std::io::Result<()> {
103//! // Fsync every 500ms (default is 200ms)
104//! let wal = Walrus::with_consistency_and_schedule(
105//! ReadConsistency::StrictlyAtOnce,
106//! FsyncSchedule::Milliseconds(500)
107//! )?;
108//!
109//! // Fsync after every single write (maximum durability, lower throughput)
110//! let wal = Walrus::with_consistency_and_schedule(
111//! ReadConsistency::StrictlyAtOnce,
112//! FsyncSchedule::SyncEach
113//! )?;
114//!
115//! // Never fsync (maximum throughput, no durability guarantees)
116//! let wal = Walrus::with_consistency_and_schedule(
117//! ReadConsistency::StrictlyAtOnce,
118//! FsyncSchedule::NoFsync
119//! )?;
120//! # Ok(())
121//! # }
122//! ```
123//!
124//! ## Namespace Isolation
125//!
126//! Create isolated WAL instances with separate storage directories:
127//!
128//! ```rust,no_run
129//! use walrus_rust::{Walrus, ReadConsistency, FsyncSchedule};
130//!
131//! # fn main() -> std::io::Result<()> {
132//! // Create a namespaced WAL (stored in wal_files/<sanitized-key>/)
133//! let wal1 = Walrus::new_for_key("tenant-123")?;
134//! let wal2 = Walrus::new_for_key("tenant-456")?;
135//!
136//! // With custom consistency
137//! let wal = Walrus::with_consistency_for_key(
138//! "my-app",
139//! ReadConsistency::AtLeastOnce { persist_every: 100 }
140//! )?;
141//!
142//! // With full configuration
143//! let wal = Walrus::with_consistency_and_schedule_for_key(
144//! "my-app",
145//! ReadConsistency::AtLeastOnce { persist_every: 1000 },
146//! FsyncSchedule::Milliseconds(500)
147//! )?;
148//! # Ok(())
149//! # }
150//! ```
151//!
152//! ## Storage Backends
153//!
154//! Walrus supports two storage backends that can be selected at runtime:
155//!
156//! ### FD Backend (File Descriptor) - Default
157//!
158//! Uses file descriptors with `pread`/`pwrite` syscalls for I/O operations. This is the
159//! default backend and requires Unix-specific APIs.
160//!
161//! **Batch Operations on Linux:**
162//! - When running on Linux, batch operations (`batch_append_for_topic` and `batch_read_for_topic`)
163//! automatically use io_uring for high-performance parallel I/O submission
164//! - Regular single-entry operations use standard `pread`/`pwrite` syscalls
165//!
166//! **O_SYNC Mode:**
167//! - When `FsyncSchedule::SyncEach` is configured, files are opened with the `O_SYNC` flag,
168//! making every write synchronous
169//!
170//! - **Works on**: Unix systems (Linux, macOS, BSD)
171//! - **Best for**: Batch operations on Linux (io_uring), general-purpose workloads
172//! - **Default**: Enabled
173//!
174//! ### Mmap Backend (Memory-Mapped Files)
175//!
176//! Uses memory-mapped files for direct memory access. Batch operations fall back to
177//! sequential reads/writes without io_uring acceleration.
178//!
179//! - **Works on**: All platforms
180//! - **Best for**: Windows, or when FD backend is incompatible
181//! - **Default**: Disabled (use `disable_fd_backend()` to enable)
182//!
183//! ### Selecting a Backend
184//!
185//! ```rust,no_run
186//! use walrus_rust::{enable_fd_backend, disable_fd_backend};
187//!
188//! // Use FD backend (default - uses io_uring for batches on Linux)
189//! enable_fd_backend();
190//!
191//! // Use mmap backend (no io_uring, sequential batch operations)
192//! disable_fd_backend();
193//! ```
194//!
195//! **Important**: Backend selection must be done before creating any `Walrus` instances.
196//!
197//! ## Environment Variables
198//!
199//! - `WALRUS_DATA_DIR`: Change storage location (default: `./wal_files`)
200//! - `WALRUS_INSTANCE_KEY`: Default namespace for all instances
201//! - `WALRUS_QUIET=1`: Suppress debug output
202//!
203//! ```bash
204//! # Example: Use a custom data directory
205//! export WALRUS_DATA_DIR=/var/lib/myapp/wal
206//!
207//! # Example: Set default namespace
208//! export WALRUS_INSTANCE_KEY=production
209//!
210//! # Example: Quiet mode
211//! export WALRUS_QUIET=1
212//! ```
213//!
214//! ## Performance Characteristics
215//!
216//! - **Block size**: 10MB per block
217//! - **Batch limits**: Up to 2,000 entries or ~10GB payload per batch
218//! - **Default fsync interval**: 200ms
219//! - **File organization**: 100 blocks per file (1GB files)
220//!
221//! ## Types
222//!
223//! ```rust
224//! # use walrus_rust::Entry;
225//! // Entry returned by read operations
226//! pub struct Entry {
227//! pub data: Vec<u8>,
228//! }
229//! ```
230//!
231//! ## API Reference
232//!
233//! ### Constructors
234//!
235//! - [`Walrus::new()`]: Default constructor (StrictlyAtOnce, 200ms fsync)
236//! - [`Walrus::with_consistency()`]: Set read consistency model
237//! - [`Walrus::with_consistency_and_schedule()`]: Set consistency and fsync policy
238//! - [`Walrus::new_for_key()`]: Create namespaced instance
239//! - [`Walrus::with_consistency_for_key()`]: Namespaced with consistency
240//! - [`Walrus::with_consistency_and_schedule_for_key()`]: Full namespaced configuration
241//!
242//! ### Write Operations
243//!
244//! - [`Walrus::append_for_topic()`]: Append single entry to topic
245//! - [`Walrus::batch_append_for_topic()`]: Atomic batch write (up to 2,000 entries)
246//!
247//! ### Read Operations
248//!
249//! - [`Walrus::read_next()`]: Read next entry (checkpoint=true consumes, false peeks)
250//! - [`Walrus::batch_read_for_topic()`]: Read multiple entries up to byte limit
251
252#![recursion_limit = "256"]
253pub mod wal;
254pub use wal::{
255 Entry, FsyncSchedule, ReadConsistency, WalIndex, Walrus, disable_fd_backend, enable_fd_backend,
256};