pub struct CacheLock { /* private fields */ }Expand description
A file lock for cache operations.
The lock is held for the lifetime of this struct and automatically released when dropped. Lock acquisition and release are tracked for deadlock detection.
Implementations§
Source§impl CacheLock
impl CacheLock
Sourcepub async fn acquire(cache_dir: &Path, source_name: &str) -> Result<Self>
pub async fn acquire(cache_dir: &Path, source_name: &str) -> Result<Self>
Acquires an exclusive lock for a specific source in the cache directory.
Creates and acquires an exclusive file lock for the specified source name. Uses non-blocking lock attempts with exponential backoff and timeout.
§Lock File Management
- Creates
.locks/directory if needed - Creates
{source_name}.lockfile - Acquires exclusive access via OS file locking
- Keeps file handle open to maintain lock
§Behavior
- Timeout: 30-second default (configurable via
acquire_with_timeout) - Non-blocking:
try_lock_exclusive()in async retry loop - Backoff: 10ms → 20ms → 40ms… up to 500ms max
- Fair access: FIFO order typically
- Interruptible: Process signals work
§Lock File Location
Format: {cache_dir}/.locks/{source_name}.lock
Example: ~/.agpm/cache/.locks/community.lock
§Errors
- Permission denied
- Disk space exhausted
- Timeout acquiring lock
§Platform Support
- Windows: Win32
LockFileAPI - Unix: POSIX
fcntl()locking
§Examples
use agpm_cli::cache::lock::CacheLock;
use std::path::Path;
let lock = CacheLock::acquire(cache_dir, "my-source").await?;
// Lock released on dropSourcepub async fn acquire_with_timeout(
cache_dir: &Path,
source_name: &str,
timeout: Duration,
) -> Result<Self>
pub async fn acquire_with_timeout( cache_dir: &Path, source_name: &str, timeout: Duration, ) -> Result<Self>
Acquires an exclusive lock with a specified timeout.
Uses exponential backoff (10ms → 500ms) without blocking the async runtime.
§Errors
Returns timeout error if lock cannot be acquired within the specified duration.
§Examples
use agpm_cli::cache::lock::CacheLock;
use std::time::Duration;
use std::path::Path;
let lock = CacheLock::acquire_with_timeout(
cache_dir, "my-source", Duration::from_secs(10)
).await?;Acquires a shared (read) lock for a specific source in the cache directory.
Multiple processes can hold shared locks simultaneously, but a shared lock blocks exclusive lock acquisition. Use this for operations that can safely run in parallel, like worktree creation (each SHA writes to a different subdir).
§Lock Semantics
- Shared locks: Multiple holders allowed simultaneously
- Exclusive locks: Blocked while any shared lock is held
- Shared + Exclusive: Shared lock blocks until exclusive is released
§Use Cases
- Worktree creation: Multiple SHAs can create worktrees in parallel
- Read-only operations on shared state
§Examples
use agpm_cli::cache::lock::CacheLock;
use std::path::Path;
// Multiple processes can hold this simultaneously
let lock = CacheLock::acquire_shared(cache_dir, "bare-worktree-owner_repo").await?;
// Lock released on dropAcquires a shared (read) lock with a specified timeout.
Uses exponential backoff (10ms → 500ms) without blocking the async runtime.
§Errors
Returns timeout error if lock cannot be acquired within the specified duration.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for CacheLock
impl RefUnwindSafe for CacheLock
impl Send for CacheLock
impl Sync for CacheLock
impl Unpin for CacheLock
impl UnwindSafe for CacheLock
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more