atomicfile

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package atomicfile centralises crash-safe file writes used across cloop's persistent stores (state, profile, checkpoint, kb, alert, eval, metrics, trace, daemon, and more).

Why a separate package: until this consolidation, ~17 packages each carried their own near-identical writeAtomic helper. Variants drifted (some skipped chmod, some forgot the cleanup-on-error defer, none flushed the parent directory inode). Centralising the helper lets us fix durability bugs once and have every store benefit, instead of chasing copy-pasted regressions.

Crash semantics: data is staged in a sibling .tmp file in the same directory as the target, then fsynced and renamed into place. POSIX rename within a directory is atomic with respect to concurrent readers, so they always see either the previous valid file or the new valid file — never a zero-byte or truncated one.

Durability: after the rename, the parent directory's inode is fsynced so the new directory entry survives a power loss. Without that step the file's data is on disk but the rename can be lost on crash, leaving the previous content (best case) or — if the previous file was being replaced — neither the old name nor the new content visible (worst case).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func QuarantineCorrupt

func QuarantineCorrupt(path string) string

QuarantineCorrupt renames path aside as path + ".corrupt-<unix>" so a Load callsite can recover from an unparseable file by treating it as absent and initialising a fresh store. The original bytes are preserved next to the original location for forensic inspection (a user can diff or restore them).

Use this from Load functions whose parsers (json.Unmarshal, yaml.Unmarshal, etc.) reject the file's contents — typically because:

  • a previous binary version wrote a different schema,
  • a power loss landed before pkg/atomicfile (or in a non-atomic legacy write path) and left a zero-byte/truncated file,
  • a user manually edited the file and saved invalid syntax.

Returns the new path on success and "" if the rename failed (e.g. read-only filesystem). Callers should treat a "" return as a soft failure: log it and fall back to the in-memory zero value WITHOUT removing the original — the next process restart can retry the quarantine. Never returns an error so the recovery path itself can't add new failure modes to a Load that's already trying to dig out of corruption.

func Write

func Write(path string, data []byte, mode os.FileMode) error

Write atomically writes data to path with the given file mode.

On success, path contains exactly data and has mode permissions. On any failure, path is left untouched and any staged .tmp file is cleaned up.

The parent directory of path must exist; Write does not call MkdirAll. (Callers typically know the directory was already created during init.)

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL