Skip to main content

entelix_persistence/
error.rs

1//! Crate-internal error type. Public APIs map this back into
2//! `entelix_core::Error::Persistence` (or `Provider`) at the
3//! orchestration layer.
4
5use thiserror::Error;
6
7/// Result alias used inside `entelix-persistence`.
8pub type PersistenceResult<T> = std::result::Result<T, PersistenceError>;
9
10/// Errors that the persistence layer surfaces to its callers.
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum PersistenceError {
14    /// The lock was held by another process when a non-blocking
15    /// `try_acquire` returned. Carries the lock key for diagnostics.
16    #[error("lock held: {key}")]
17    LockHeld {
18        /// Lock key that could not be acquired.
19        key: String,
20    },
21
22    /// The lock could not be acquired within the configured deadline.
23    #[error("lock acquire timed out for key '{key}' after {attempts} attempts")]
24    LockAcquireTimeout {
25        /// Lock key that timed out.
26        key: String,
27        /// Attempt count that was exhausted.
28        attempts: u32,
29    },
30
31    /// Schema version mismatch — a payload tagged with a version this
32    /// build does not understand.
33    #[error(
34        "schema version mismatch: payload version {payload}, build version range \
35         [{min}, {current}]"
36    )]
37    SchemaVersionMismatch {
38        /// Version observed in the payload.
39        payload: u32,
40        /// Lowest version this build accepts.
41        min: u32,
42        /// Highest version this build understands.
43        current: u32,
44    },
45
46    /// Configuration mistake — connection string malformed, builder
47    /// missing required field, etc.
48    #[error("configuration error: {0}")]
49    Config(String),
50
51    /// Generic backend failure — `sqlx` / `redis` error, network
52    /// drop, malformed payload. Contains the original error message.
53    #[error("backend failure: {0}")]
54    Backend(String),
55
56    /// JSON encode/decode failure on a stored payload.
57    #[error(transparent)]
58    Serde(#[from] serde_json::Error),
59}
60
61impl From<PersistenceError> for entelix_core::Error {
62    fn from(err: PersistenceError) -> Self {
63        match err {
64            PersistenceError::LockHeld { .. } | PersistenceError::LockAcquireTimeout { .. } => {
65                Self::invalid_request(err.to_string())
66            }
67            PersistenceError::SchemaVersionMismatch { .. } => Self::config(err.to_string()),
68            PersistenceError::Config(msg) => Self::config(msg),
69            PersistenceError::Backend(msg) => Self::provider_network(msg),
70            PersistenceError::Serde(e) => Self::Serde(e),
71        }
72    }
73}