use std::time::Duration;
use async_trait::async_trait;
use thiserror::Error;
use crate::{InstanceInfo, InstanceRole, LeaderAnnounce};
#[derive(Debug, Error)]
pub enum LockError {
#[error("lock held by another owner: {0}")]
Contended(String),
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("lock backend not available: {0}")]
Unavailable(&'static str),
}
#[async_trait]
pub trait LockGuard: Send + Sync {
async fn release(&mut self);
}
#[async_trait]
pub trait CoordinationLock: Send + Sync {
async fn acquire(&self, key: &str, lease: Duration) -> Result<Box<dyn LockGuard>, LockError>;
}
#[derive(Debug, Error)]
pub enum RegistryError {
#[error("instance not found: {0}")]
NotFound(String),
#[error("registry store error: {0}")]
Store(String),
}
#[async_trait]
pub trait InstanceRegistry: Send + Sync {
async fn register(&self, info: InstanceInfo) -> Result<(), RegistryError>;
async fn set_role(&self, instance_id: &str, role: InstanceRole) -> Result<(), RegistryError>;
async fn deregister(&self, instance_id: &str) -> Result<(), RegistryError>;
async fn list(&self, group: &str) -> Result<Vec<InstanceInfo>, RegistryError>;
}
#[derive(Debug, Error)]
pub enum ElectionError {
#[error("lease contended: {0}")]
Contended(String),
#[error("election store error: {0}")]
Store(String),
}
#[async_trait]
pub trait LeaderElector: Send + Sync {
async fn try_acquire(&self, ttl: Duration) -> Result<bool, ElectionError>;
async fn renew(&self) -> Result<bool, ElectionError>;
async fn current(&self) -> Result<Option<LeaderAnnounce>, ElectionError>;
async fn resign(&self) -> Result<(), ElectionError>;
}