fslock

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package fslock provides an advisory, cross-process file lock used to serialize read-modify-write cycles over the CLI's on-disk state.

Why it exists

Every mutation of keys.json (the registry), keystore.json (the file vault), and config.json is a load → modify → atomic-rename cycle. The atomic rename prevents a torn file, but it does NOT prevent a lost update: two concurrent korbit-cli processes — the expected case is a long-running monitor bot plus ad-hoc human commands — can each read the same snapshot and last-writer-wins the whole file. For the file vault that can silently drop a freshly-added key's PRIVATE material while its registry record survives (unrecoverable; forces a portal rotation). An advisory lock held across the whole read-modify-write closes that window.

The lock

Lock takes an EXCLUSIVE advisory lock on a dedicated sidecar file (e.g. "<home>/keys.json.lock") — never on the data file itself, so the data file's atomic-rename is undisturbed. The lock is advisory: it only excludes other callers that also go through Lock on the same path. Reads that rely on the atomic rename for a consistent snapshot need no lock.

Blocking acquire is intentional. These critical sections are milliseconds (load a small JSON file, mutate, atomic-rename), so a contending process simply waits its turn rather than failing.

Crash safety

OS advisory locks (flock on unix, LockFileEx on Windows) are released automatically when the owning process exits or its file descriptor/handle is closed — including on a crash or kill. So there is NO stale-lock recovery to do and the lock file is never deleted by the CLI (deleting it would race a concurrent acquirer holding it open). A leftover ".lock" file is expected and harmless; it carries only a human-readable note (see lockNote) explaining that a user is free to delete it whenever no korbit-cli process is running.

Lock ordering (callers' contract)

fslock itself imposes no ordering, but its callers must: the only nested acquisition in this codebase is keys.Manager holding the registry lock (keys.json.lock) while it drives the file vault's Set/Delete, which take the SEPARATE vault lock (keystore.json.lock). That nesting is safe ONLY because the two locks are different files. The fixed order is registry → vault, never the reverse, and nothing in the vault layer may acquire the registry lock — otherwise two processes could deadlock. See internal/keys/doc.go and internal/keystore/doc.go.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Lock

func Lock(path string) (release func(), err error)

Lock acquires an exclusive advisory lock on the sidecar file at path (conventionally "<datafile>.lock"), creating it 0600 if needed. The parent directory is created 0700 first, because the lock may be taken before the CLI home exists (`key add` creates it on first use). It blocks until the lock is held, then returns a release func the caller MUST defer; release unlocks and closes the descriptor/handle. A non-nil error means the lock was NOT acquired and release is nil.

Types

This section is empty.

Jump to

Keyboard shortcuts

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