use std::{fs::File, time::Duration};
use fs2::FileExt as _;
use super::{
super::store::LeaseStore, FileRuntimeStore, RuntimeError, fs_util, lock_unpoisoned, store_error,
};
pub(super) struct HeldLease {
owner: String,
_file: File,
}
impl LeaseStore for FileRuntimeStore {
fn acquire_lease(&self, key: &str, owner: &str, _ttl: Duration) -> Result<bool, RuntimeError> {
let mut held = lock_unpoisoned(&self.held_leases);
if held.contains_key(key) {
return Ok(false);
}
let path = self
.leases_dir()
.join(format!("{}.lock", fs_util::encode_component(key)));
let file = fs_util::open_lock_file(&path)?;
match file.try_lock_exclusive() {
Ok(()) => {
held.insert(
key.to_string(),
HeldLease {
owner: owner.to_string(),
_file: file,
},
);
Ok(true)
}
Err(error) if error.raw_os_error() == fs2::lock_contended_error().raw_os_error() => {
Ok(false)
}
Err(error) => Err(store_error(&format!("lock '{}'", path.display()), error)),
}
}
fn release_lease(&self, key: &str, owner: &str) -> Result<(), RuntimeError> {
let mut held = lock_unpoisoned(&self.held_leases);
if held.get(key).is_some_and(|lease| lease.owner == owner) {
held.remove(key);
}
Ok(())
}
}