use async_trait::async_trait;
use std::fmt;
#[derive(Debug)]
pub enum DistributedError {
StoreError(String),
LockError(String),
NotFound(String),
}
impl fmt::Display for DistributedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::StoreError(e) => write!(f, "Store error: {}", e),
Self::LockError(e) => write!(f, "Lock error: {}", e),
Self::NotFound(e) => write!(f, "Not found: {}", e),
}
}
}
impl std::error::Error for DistributedError {}
#[async_trait]
pub trait DistributedStore: Send + Sync {
async fn get(&self, domain: &str, key: &str) -> Result<Option<Vec<u8>>, DistributedError>;
async fn set(
&self,
domain: &str,
key: &str,
value: &[u8],
ttl_sec: Option<u64>,
) -> Result<(), DistributedError>;
async fn delete(&self, domain: &str, key: &str) -> Result<(), DistributedError>;
}
#[derive(Debug, Clone)]
pub struct LockOptions {
pub ttl_ms: u64,
pub retry_count: u32,
pub retry_delay_ms: u64,
}
impl Default for LockOptions {
fn default() -> Self {
Self {
ttl_ms: 10_000,
retry_count: 5,
retry_delay_ms: 200,
}
}
}
#[derive(Debug, Clone)]
pub struct Guard {
pub resource_key: String,
pub token: String,
}
#[async_trait]
pub trait DistributedLock: Send + Sync {
async fn acquire(
&self,
resource_key: &str,
options: LockOptions,
) -> Result<Guard, DistributedError>;
async fn release(&self, guard: Guard) -> Result<(), DistributedError>;
async fn extend(&self, guard: &Guard, additional_ttl_ms: u64) -> Result<(), DistributedError>;
}