lock

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package lock provides cross-process advisory locking around .agent-memory/meta/lock via github.com/gofrs/flock. The kernel owns lock state, so process death releases the lock automatically — no application stale-recovery code is needed.

See docs/patterns/cross-process-locking.md for the design rationale and docs/spikes/s3-results.md for the empirical validation that motivated this approach.

Index

Constants

This section is empty.

Variables

View Source
var ErrLockHeld = errors.New("lock held by another process")

ErrLockHeld is returned by Acquire when the lock cannot be obtained within AcquireOpts.WaitTimeout (or immediately, if WaitTimeout is zero).

Functions

func MetadataPath

func MetadataPath(lockPath string) string

MetadataPath returns the sidecar file path where Acquire writes the Metadata JSON for a lock at lockPath.

Types

type AcquireOpts

type AcquireOpts struct {
	// WaitTimeout caps how long Acquire blocks waiting for a contended lock:
	//   0  → TryLock once and return ErrLockHeld immediately if unavailable.
	//   >0 → TryLock then poll (every ~10ms) until the lock is available or
	//        the timeout expires.
	WaitTimeout time.Duration

	// Owner is the metadata to write into the lock file on successful
	// acquisition. Empty fields are filled in: OwnerPID defaults to
	// os.Getpid(), AcquiredAt defaults to time.Now().UTC().
	Owner Metadata
}

AcquireOpts configures Acquire.

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

Lock is a held advisory lock. Release it via Release(); the OS releases the underlying lock automatically on process exit even if Release is not called.

func Acquire

func Acquire(path string, opts AcquireOpts) (*Lock, error)

Acquire opens (creating if missing) the file at path and tries to acquire an exclusive OS advisory lock on it.

If the lock is held by another process and AcquireOpts.WaitTimeout is zero, Acquire returns ErrLockHeld immediately. If WaitTimeout is positive, Acquire polls until the lock is available or the timeout expires.

On success, Acquire writes the owner metadata into the lock file. This is best-effort and never affects correctness.

The lock file persists on disk; only the OS lock is transient. Callers should typically point path at .agent-memory/meta/lock.

func (*Lock) Path

func (l *Lock) Path() string

Path returns the lock file path this Lock was acquired against.

func (*Lock) Release

func (l *Lock) Release() error

Release closes the lock file. The kernel releases the OS lock atomically as part of close. The lock file itself persists.

Calling Release on an already-released Lock is a no-op.

type Metadata

type Metadata struct {
	OwnerPID   int       `json:"owner_pid"`
	OwnerID    string    `json:"owner_id"`   // e.g. "claude-code-session-abc"
	OwnerKind  string    `json:"owner_kind"` // "agent" | "cli" | "cli-merge-driver" | ...
	AcquiredAt time.Time `json:"acquired_at"`
	OpID       string    `json:"op_id,omitempty"`
}

Metadata is the informational JSON written inside the lock file by the current holder. It NEVER gates correctness — the OS lock is ground truth. Stale metadata after a crashed holder is harmless: the next acquirer overwrites it.

func ReadMetadata

func ReadMetadata(lockPath string) (Metadata, error)

ReadMetadata reads the JSON metadata written by the current (or last) lock holder. Best-effort: a missing, empty, or malformed file returns an empty Metadata with no error. The OS lock is ground truth for whether the lock is held; this function exists only for status/debugging.

The metadata lives in a sidecar file (MetadataPath(lockPath)), not in the lock file itself. See the package comment for the rationale.

Jump to

Keyboard shortcuts

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