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}