Skip to main content

save_snapshot

Function save_snapshot 

Source
pub fn save_snapshot(
    snapshots_dir: &Path,
    state: &MaterializedState,
) -> Result<PathBuf>
Expand description

Save a bincode-serialized, zstd-compressed snapshot file (.snap.zst) (§5.5).

Written to a temporary file, flushed to disk, renamed into place, and the directory flushed after the rename. A snapshot is read back with no integrity check beyond the container’s own checksum, so a half-written file at the final name is a file that looks loadable and is not — and it would be the newest one, which is exactly the one a restart reaches for. Rename within a directory is atomic, so a crash leaves either the old snapshot or the new one, never a splice; sync_directory is what makes the winner of that race survive the power loss that caused it (0.13.13, W8.3).

§This blocks, and it is not a small block (0.13.11, W8.1)

bincode over the whole state, zstd over the result, a file write and an fsync — CPU and disk, both unbounded in the size of the graph, and none of it yielding. Called from an async task it stalls that runtime worker for the whole duration, which at 100K edges is the two seconds §9 budgets for it. Every async caller inside the crate goes through save_and_prune; a caller outside it wants tokio::task::spawn_blocking around this, and the signature stays synchronous so that they can have it.

§What a failure here means (0.14.23, C-2, D-240)

DbError::SnapshotWriteFailed, naming the snapshot and the step. Not DbError::ReplayCorrupt, which is what every failure in here answered until 0.14.23 and which says the ledger is damaged: a full disk, a read-only directory or a lost temp file said the worst thing this system can say about itself. Nothing here can damage the ledger — the log is untouched, the previous anchor still stands, and Doctrine VI makes the cost of losing a snapshot a slower start rather than a wrong answer.