Skip to main content

ash_lock/
error.rs

1//! Error types for `ash-lock`.
2
3use std::time::Duration;
4use thiserror::Error;
5
6/// The result type used throughout the public API.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Errors that can occur while acquiring, renewing, or releasing a lock.
10#[derive(Debug, Error)]
11pub enum Error {
12    /// The lock is currently held by another owner and could not be acquired
13    /// within the allotted time / attempts.
14    #[error("resource `{resource}` is already locked")]
15    Contended {
16        /// The contended resource key.
17        resource: String,
18    },
19
20    /// The acquire attempt exceeded the configured wait budget.
21    #[error("timed out after {waited:?} waiting for `{resource}`")]
22    Timeout {
23        /// The contended resource key.
24        resource: String,
25        /// How long we waited before giving up.
26        waited: Duration,
27    },
28
29    /// A renew or release referenced a fencing token the backend no longer
30    /// recognises — typically because the lease already expired and was
31    /// re-acquired by someone else.
32    #[error("fencing token {token} for `{resource}` is stale (current: {current})")]
33    StaleToken {
34        /// The contended resource key.
35        resource: String,
36        /// The token the caller presented.
37        token: u64,
38        /// The token the backend currently considers valid.
39        current: u64,
40    },
41
42    /// The lock's lease expired locally before it could be renewed — the guard
43    /// is now poisoned and its fencing token must not be trusted.
44    #[error("lease for `{resource}` expired (guard poisoned)")]
45    LeaseExpired {
46        /// The resource whose lease lapsed.
47        resource: String,
48    },
49
50    /// A cluster / transport level failure (network partition, no reachable
51    /// nodes, RPC error, …).
52    #[error("cluster error: {0}")]
53    Cluster(String),
54
55    /// Configuration was rejected (e.g. empty seed list, zero TTL).
56    #[error("invalid configuration: {0}")]
57    Config(String),
58}
59
60impl Error {
61    /// Convenience constructor for cluster/transport failures.
62    // Only referenced from tests and the `ash-time` / `etcd` feature paths.
63    #[cfg_attr(
64        not(any(test, feature = "ash-time", feature = "etcd")),
65        allow(dead_code)
66    )]
67    pub(crate) fn cluster(msg: impl Into<String>) -> Self {
68        Error::Cluster(msg.into())
69    }
70}