Validate each WAL segment for startup integrity. Returns `Err` if any non-empty segment contains no valid WAL records — a reliable signal that the segment was corrupted (wrong magic, truncated header, etc.) rather than simply rolled over empty. This check is intentionally strict: a segment file with content that does not parse as WAL records is treated as fatal corruption, not as an empty WAL. T
(&self)
| 18 | /// empty WAL. The WAL replay path is lenient (stops at the first invalid |
| 19 | /// record) — this method is the complementary hard check run at startup. |
| 20 | pub fn validate_for_startup(&self) -> crate::Result<()> { |
| 21 | let segments = |
| 22 | nodedb_wal::segment::discover_segments(&self.wal_dir).map_err(crate::Error::Wal)?; |
| 23 | |
| 24 | for seg in &segments { |
| 25 | let file_len = std::fs::metadata(&seg.path).map(|m| m.len()).unwrap_or(0); |
| 26 | |
| 27 | if file_len == 0 { |
| 28 | continue; |
| 29 | } |
| 30 | |
| 31 | let info = nodedb_wal::recovery::recover(&seg.path).map_err(crate::Error::Wal)?; |
| 32 | |
| 33 | if info.end_offset == 0 { |
| 34 | return Err(crate::Error::SegmentCorrupted { |
| 35 | detail: format!( |
| 36 | "WAL segment '{}' is non-empty ({file_len} bytes) but contains no valid \ |
| 37 | WAL records — the segment appears to be corrupted", |
| 38 | seg.path.display() |
| 39 | ), |
| 40 | }); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | Ok(()) |
| 45 | } |
| 46 | |
| 47 | /// Replay all committed records from the WAL. |
| 48 | pub fn replay(&self) -> crate::Result<Vec<WalRecord>> { |
no test coverage detected