Documentation
¶
Overview ¶
Package locks wraps gofrs/flock with typed-reason acquire helpers for the kernel-managed advisory locks required by and 440b, plus a non-blocking single-attempt try (TryAcquire) for the retention pruner.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LockReason ¶
type LockReason string
LockReason classifies the outcome of an acquire attempt, in the vocabulary shares with. ReasonNone covers a successful acquire.
const ( ReasonNone LockReason = "none" ReasonLockTimeout LockReason = "lock_timeout" ReasonLockContended LockReason = "lock_contended" ReasonLockAcquireError LockReason = "lock_acquire_error" )
func Acquire ¶
func Acquire(path string, timeout time.Duration) (release func(), reason LockReason, err error)
Acquire takes an exclusive advisory lock on path with the given acquisition timeout. Production callers (step (1) and 440b) pass 2*time.Second; tests may pass a shorter duration.
On success, release closes the underlying lock object — which unlocks the file and closes the file descriptor — and reason is ReasonNone. On timeout, reason is ReasonLockTimeout and err is the context deadline error. On any other lock-syscall failure, reason is ReasonLockAcquireError and err is the underlying error so callers can map it to the error-category vocabulary.
This helper locks exactly the path it is given and does not own the data file. Callers pass a dedicated sidecar lock path (`<settings>.lock`, `<session>.json.lock`) that is never the target of an atomic rename, per step (1) — locking the renamed-over data file would not provide cross-process mutual exclusion. If the lock file does not exist, gofrs/flock creates it at mode 0600 before attempting the lock.
func AcquireAt ¶
func AcquireAt(dir *os.File, name string, timeout time.Duration) (release func(), reason LockReason, err error)
AcquireAt takes the same kernel flock as Acquire, so the two exclude each other on one sidecar.
func TryAcquire ¶
func TryAcquire(path string) (release func(), reason LockReason, err error)
TryAcquire makes exactly one non-blocking attempt to take an exclusive advisory lock on path and returns immediately — there is no wait, retry, or timeout. The retention pruner uses it to probe a session's resume lock before deleting the file: a single try with "no wait timeout applies."
On success, release closes the underlying lock object (unlock + close fd) and reason is ReasonNone. When another holder currently owns the lock, release is nil, reason is ReasonLockContended, and err is nil — a non-error skip path the pruner must distinguish from a real failure so it can leave the live session alone silently. On a lock-syscall/construction failure, release is nil, reason is ReasonLockAcquireError, and err is the underlying error.
Unlike Acquire(path, 0), this actually attempts the lock: Acquire with a zero timeout hands gofrs/flock an already-expired context, so TryLockContext reports a timeout without ever calling the lock syscall. TryAcquire calls the single-attempt TryLock directly instead. The same sidecar-path contract as Acquire applies: callers pass a dedicated lock path, never an atomically renamed-over data file.