reddb-io-server 1.12.0

RedDB server-side engine: storage, runtime, replication, MCP, AI, and the gRPC/HTTP/RedWire/PG-wire dispatchers. Re-exported by the umbrella `reddb` crate.
Documentation
//! Write-Ahead Log (WAL) for RedDB durability.
//!
//! Handles crash recovery by logging all changes before they are applied to the database file.
//!
//! The persisted WAL header, record envelope, segment sizing, compression tags,
//! and checksums are `reddb-file` contracts. This module owns runtime
//! orchestration: append buffering, fsync policy, checkpointing, and recovery.

pub mod append_coordinator;
pub mod archiver;
pub mod checkpoint;
pub mod checkpointer_task;
pub mod group_commit;
pub mod reader;
pub mod record;
pub mod recovery;
pub mod rmgr;
pub mod transaction;
pub mod writer;

pub use append_coordinator::WalAppendCoordinator;
pub use archiver::{
    archive_change_records, archive_snapshot, load_archived_change_records, load_backup_head,
    load_snapshot_manifest, load_unified_manifest, load_wal_segment_manifest, publish_backup_head,
    publish_snapshot_manifest, publish_unified_manifest, publish_unified_manifest_for_prefix,
    publish_wal_segment_manifest, WalArchiver,
};
pub use checkpoint::{CheckpointError, CheckpointMode, CheckpointResult, Checkpointer};
pub use group_commit::GroupCommit;
pub use reader::WalReader;
pub use record::{RecordType, WalRecord};
pub use recovery::{PointInTimeRecovery, RecoveryResult, RestorePoint};
pub use transaction::{Transaction, TransactionManager, TxError, TxState};
pub use writer::WalWriter;

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use std::time::{SystemTime, UNIX_EPOCH};

    #[test]
    fn test_wal_write_read() {
        let timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_nanos();
        let dir = std::env::temp_dir().join(format!("reddb_wal_test_{}", timestamp));
        let _ = fs::create_dir_all(&dir);
        let path = reddb_file::layout::wal_component_temp_path(
            &dir,
            "mod",
            "write-read",
            std::process::id(),
        );
        if path.exists() {
            fs::remove_file(&path).unwrap();
        }

        // Write
        {
            let mut writer = WalWriter::open(&path).unwrap();

            let rec1 = WalRecord::Begin { tx_id: 100 };
            writer.append(&rec1).unwrap();

            let rec2 = WalRecord::PageWrite {
                tx_id: 100,
                page_id: 5,
                data: vec![1, 2, 3, 4],
            };
            writer.append(&rec2).unwrap();

            let rec3 = WalRecord::Commit { tx_id: 100 };
            writer.append(&rec3).unwrap();
        }

        // Read
        {
            let reader = WalReader::open(&path).unwrap();
            let records: Vec<_> = reader.iter().map(|r| r.unwrap().1).collect();

            assert_eq!(records.len(), 3);

            match &records[0] {
                WalRecord::Begin { tx_id } => assert_eq!(*tx_id, 100),
                _ => panic!("Wrong type"),
            }

            match &records[1] {
                WalRecord::PageWrite {
                    tx_id,
                    page_id,
                    data,
                } => {
                    assert_eq!(*tx_id, 100);
                    assert_eq!(*page_id, 5);
                    assert_eq!(*data, vec![1, 2, 3, 4]);
                }
                _ => panic!("Wrong type"),
            }

            match &records[2] {
                WalRecord::Commit { tx_id } => assert_eq!(*tx_id, 100),
                _ => panic!("Wrong type"),
            }
        }

        // Cleanup
        if path.exists() {
            fs::remove_file(path).unwrap();
        }
        if dir.exists() {
            fs::remove_dir(dir).unwrap();
        }
    }
}