distributed_lock_file/
provider.rs

1//! File lock provider implementation.
2
3use std::path::{Path, PathBuf};
4
5use distributed_lock_core::error::{LockError, LockResult};
6use distributed_lock_core::traits::LockProvider;
7
8use crate::lock::FileDistributedLock;
9
10/// Builder for file-based lock provider configuration.
11pub struct FileLockProviderBuilder {
12    directory: Option<PathBuf>,
13}
14
15impl FileLockProviderBuilder {
16    /// Creates a new builder.
17    pub fn new() -> Self {
18        Self { directory: None }
19    }
20
21    /// Sets the directory for lock files.
22    ///
23    /// The directory will be created if it doesn't exist.
24    pub fn directory(mut self, path: impl Into<PathBuf>) -> Self {
25        self.directory = Some(path.into());
26        self
27    }
28
29    /// Builds the provider.
30    ///
31    /// # Errors
32    ///
33    /// Returns an error if no directory is specified or if the directory
34    /// cannot be created.
35    pub fn build(self) -> LockResult<FileLockProvider> {
36        let directory = self
37            .directory
38            .ok_or_else(|| LockError::InvalidName("directory not specified".to_string()))?;
39
40        // Ensure directory exists
41        std::fs::create_dir_all(&directory)
42            .map_err(|e| LockError::InvalidName(format!("failed to create directory: {e}")))?;
43
44        Ok(FileLockProvider { directory })
45    }
46}
47
48impl Default for FileLockProviderBuilder {
49    fn default() -> Self {
50        Self::new()
51    }
52}
53
54/// Provider for file-based distributed locks.
55///
56/// Uses OS-level file locking to provide mutual exclusion across processes.
57/// Works on any POSIX system (Linux, macOS) and Windows.
58pub struct FileLockProvider {
59    directory: PathBuf,
60}
61
62impl FileLockProvider {
63    /// Returns a new builder for configuring the provider.
64    pub fn builder() -> FileLockProviderBuilder {
65        FileLockProviderBuilder::new()
66    }
67
68    /// Creates a provider using the specified directory.
69    ///
70    /// Convenience method for simple use cases.
71    pub fn new(directory: impl Into<PathBuf>) -> LockResult<Self> {
72        Self::builder().directory(directory).build()
73    }
74
75    /// Returns the directory where lock files are stored.
76    pub fn directory(&self) -> &Path {
77        &self.directory
78    }
79}
80
81impl LockProvider for FileLockProvider {
82    type Lock = FileDistributedLock;
83
84    fn create_lock(&self, name: &str) -> Self::Lock {
85        FileDistributedLock::new(&self.directory, name)
86            .expect("failed to create lock from provider")
87    }
88}