Open, validate, and replay the WAL. Load the tombstone set from redb + WAL. Returns `(wal, wal_records, tombstones)`. Exits the process on unrecoverable corruption — a dirty WAL cannot be safely replayed.
(
config: &ServerConfig,
)
| 14 | /// Returns `(wal, wal_records, tombstones)`. Exits the process on unrecoverable |
| 15 | /// corruption — a dirty WAL cannot be safely replayed. |
| 16 | pub fn init_wal( |
| 17 | config: &ServerConfig, |
| 18 | ) -> anyhow::Result<( |
| 19 | Arc<WalManager>, |
| 20 | Arc<[nodedb_wal::WalRecord]>, |
| 21 | nodedb_wal::TombstoneSet, |
| 22 | )> { |
| 23 | let wal_segment_target = config.checkpoint.wal_segment_target_bytes(); |
| 24 | let wal = { |
| 25 | let mut mgr = WalManager::open_with_tuning( |
| 26 | &config.wal_dir(), |
| 27 | false, |
| 28 | wal_segment_target, |
| 29 | &config.tuning.wal, |
| 30 | )?; |
| 31 | if let Some(ref enc) = config.encryption { |
| 32 | let key = nodedb_wal::crypto::WalEncryptionKey::from_file(&enc.key_path) |
| 33 | .map_err(crate::Error::Wal)?; |
| 34 | mgr.set_encryption_ring(nodedb_wal::crypto::KeyRing::new(key))?; |
| 35 | info!(key_path = %enc.key_path.display(), "WAL encryption enabled"); |
| 36 | } |
| 37 | Arc::new(mgr) |
| 38 | }; |
| 39 | info!(next_lsn = %wal.next_lsn(), "WAL ready"); |
| 40 | |
| 41 | if let Err(e) = wal.validate_for_startup() { |
| 42 | tracing::error!( |
| 43 | error = %e, |
| 44 | "StartupError: WAL validation failed — cannot start with corrupted WAL segments" |
| 45 | ); |
| 46 | std::process::exit(1); |
| 47 | } |
| 48 | |
| 49 | let wal_records: Arc<[nodedb_wal::WalRecord]> = match wal.replay() { |
| 50 | Ok(records) => { |
| 51 | if !records.is_empty() { |
| 52 | info!(records = records.len(), "WAL records loaded for replay"); |
| 53 | } |
| 54 | Arc::from(records.into_boxed_slice()) |
| 55 | } |
| 56 | Err(e) => { |
| 57 | tracing::error!( |
| 58 | error = %e, |
| 59 | "StartupError: WAL replay failed — cannot start with a corrupt or unreadable WAL" |
| 60 | ); |
| 61 | std::process::exit(1); |
| 62 | } |
| 63 | }; |
| 64 | |
| 65 | tracing::warn!( |
| 66 | catalog = %config.catalog_path().display(), |
| 67 | "redb catalog stored unencrypted; use a dm-crypt/LUKS volume \ |
| 68 | for at-rest catalog encryption" |
| 69 | ); |
| 70 | |
| 71 | let tombstones = load_tombstones(config, &wal_records); |
| 72 | Ok((wal, wal_records, tombstones)) |
| 73 | } |
no test coverage detected