Function atomic_publish
pub fn atomic_publish<F, E>(dest: &Path, write: F) -> Result<(), E>Expand description
Publish a file atomically: write the payload to a process-unique temp
sibling of dest, then rename it over dest only after write succeeds.
An interrupted or failing write leaves any previous dest untouched — the
half-written bytes live only in the temp file, which is removed on error.
This is the single output-write choke point every emitter routes through so
a ^C (or a mid-write failure) can never truncate a good previous output.
Mirrors the fact-cache publish idiom (facts::FactsDb cache write): temp in
the destination’s own directory so the rename is a same-filesystem metadata
operation (a cross-device rename would fail), a pid suffix to isolate
concurrent writers to the same destination, and an fsync before the rename.
write receives the temp path and must create and fully write the file at
it. The path it receives does not exist when write is called (any stale
temp from this pid’s prior aborted run is cleared first), which is exactly
what a DuckDB ATTACH ... (TYPE SQLITE) requires; a streaming writer
(File::create) or a COPY ... TO names the path directly.
The error type is the caller’s: write returns Result<(), E> and the
helper’s own I/O failures surface through the same E via
E: From<std::io::Error> (satisfied by both CodeLoreError and
anyhow::Error).
§Errors
Propagates write’s error, or an I/O error from the rename step. The fsync
is best-effort (advisory durability): atomicity — the actual guarantee —
comes from write-to-temp + rename, so a filesystem that refuses the re-open
for fsync must not fail an otherwise-complete write.