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}