filelock.rs raw

use std::{
    fs::{File, TryLockError},
    path::Path,
};

use crate::Error;

/// Holds an exclusive OS-level lock for as long as the value is alive.
///
/// The lock lives on a sidecar file rather than on the queue's data file
/// itself, so that compaction can atomically replace the data file
/// without disturbing the lock. The lock is released when the value is
/// dropped (closing the file releases the OS lock).
pub struct FileLock {
    _file: File,
}

impl FileLock {
    pub fn acquire(path: &Path) -> Result<FileLock, Error> {
        let file = File::options()
            .read(true)
            .write(true)
            .create(true)
            .truncate(false)
            .open(path)?;

        match file.try_lock() {
            Ok(()) => Ok(FileLock { _file: file }),
            Err(TryLockError::WouldBlock) => Err(Error::QueueLocked),
            Err(TryLockError::Error(err)) => Err(err.into()),
        }
    }
}