Skip to main content

uni_db/api/
multi_agent.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2026 Dragonscale Team
3
4//! Multi-agent access — read-only mode and write lease abstraction.
5//!
6//! Supports multi-reader / single-writer architectures where multiple
7//! processes can open the same database for reads, while writes are
8//! coordinated through a lease mechanism.
9
10use uni_common::Result;
11
12/// Write lease strategy for multi-agent access.
13///
14/// Determines how write access is coordinated across multiple database instances.
15#[non_exhaustive]
16pub enum WriteLease {
17    /// Local single-process lock (default behavior — no external coordination).
18    Local,
19    /// DynamoDB-based distributed lease. Stores config but is not yet implemented.
20    DynamoDB { table: String },
21    /// Custom lease provider via trait object.
22    Custom(Box<dyn WriteLeaseProvider>),
23}
24
25/// Guard representing an acquired write lease.
26pub struct LeaseGuard {
27    /// Unique ID for this lease acquisition.
28    pub lease_id: String,
29    /// When the lease expires (must be renewed via heartbeat before expiry).
30    pub expires_at: chrono::DateTime<chrono::Utc>,
31}
32
33/// Trait for custom write lease providers.
34///
35/// Implement this trait to provide distributed write coordination
36/// (e.g., via DynamoDB, etcd, Redis, ZooKeeper).
37#[async_trait::async_trait]
38pub trait WriteLeaseProvider: Send + Sync {
39    /// Attempt to acquire the write lease. Returns `Err` if the lease is held by another writer.
40    async fn acquire(&self) -> Result<LeaseGuard>;
41
42    /// Renew the lease before it expires.
43    async fn heartbeat(&self, guard: &LeaseGuard) -> Result<()>;
44
45    /// Release the lease. Called on graceful shutdown.
46    async fn release(&self, guard: LeaseGuard) -> Result<()>;
47}
48
49impl std::fmt::Debug for WriteLease {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        match self {
52            WriteLease::Local => write!(f, "WriteLease::Local"),
53            WriteLease::DynamoDB { table } => {
54                write!(f, "WriteLease::DynamoDB {{ table: {} }}", table)
55            }
56            WriteLease::Custom(_) => write!(f, "WriteLease::Custom(...)"),
57        }
58    }
59}