Skip to main content

a3s_memory/repository/
error.rs

1use std::fmt;
2
3/// Typed failures returned by the durable memory repository.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum MemoryRepositoryError {
6    InvalidInput {
7        field: String,
8        message: String,
9    },
10    LimitExceeded {
11        resource: String,
12        limit: usize,
13        actual: usize,
14    },
15    NamespaceMismatch {
16        context: String,
17    },
18    NodeAlreadyExists {
19        node_id: String,
20    },
21    NodeNotFound {
22        node_id: String,
23    },
24    NodeRevisionNotFound {
25        node_id: String,
26        revision: u64,
27    },
28    RelationTargetNotFound {
29        node_id: String,
30        target_id: String,
31    },
32    EvidenceRequired {
33        node_id: String,
34    },
35    AdmissionNotAllowed {
36        node_id: String,
37        revision: u64,
38        current_revision: u64,
39        current_status: String,
40    },
41    RevisionConflict {
42        node_id: String,
43        expected: u64,
44        actual: u64,
45    },
46    IdempotencyConflict {
47        key: String,
48    },
49    InvalidTransition {
50        node_id: String,
51        from: String,
52        to: String,
53    },
54    InvariantViolation {
55        message: String,
56    },
57    Persistence {
58        operation: String,
59        message: String,
60    },
61}
62
63impl MemoryRepositoryError {
64    pub(crate) fn invalid(field: impl Into<String>, message: impl Into<String>) -> Self {
65        Self::InvalidInput {
66            field: field.into(),
67            message: message.into(),
68        }
69    }
70
71    pub(crate) fn invariant(message: impl Into<String>) -> Self {
72        Self::InvariantViolation {
73            message: message.into(),
74        }
75    }
76}
77
78impl fmt::Display for MemoryRepositoryError {
79    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
80        match self {
81            Self::InvalidInput { field, message } => {
82                write!(formatter, "invalid {field}: {message}")
83            }
84            Self::LimitExceeded {
85                resource,
86                limit,
87                actual,
88            } => write!(
89                formatter,
90                "{resource} exceeds its limit of {limit} (actual: {actual})"
91            ),
92            Self::NamespaceMismatch { context } => {
93                write!(formatter, "namespace mismatch in {context}")
94            }
95            Self::NodeAlreadyExists { node_id } => {
96                write!(formatter, "memory node already exists: {node_id}")
97            }
98            Self::NodeNotFound { node_id } => write!(formatter, "memory node not found: {node_id}"),
99            Self::NodeRevisionNotFound { node_id, revision } => write!(
100                formatter,
101                "memory node {node_id} revision was not found: {revision}"
102            ),
103            Self::RelationTargetNotFound { node_id, target_id } => write!(
104                formatter,
105                "relation target {target_id} for memory node {node_id} was not found"
106            ),
107            Self::EvidenceRequired { node_id } => {
108                write!(formatter, "memory node {node_id} requires evidence")
109            }
110            Self::AdmissionNotAllowed {
111                node_id,
112                revision,
113                current_revision,
114                current_status,
115            } => write!(
116                formatter,
117                "memory node {node_id} revision {revision} cannot be admitted; current revision {current_revision} is {current_status}"
118            ),
119            Self::RevisionConflict {
120                node_id,
121                expected,
122                actual,
123            } => write!(
124                formatter,
125                "memory node {node_id} revision conflict: expected {expected}, actual {actual}"
126            ),
127            Self::IdempotencyConflict { key } => {
128                write!(
129                    formatter,
130                    "idempotency key was reused with different input: {key}"
131                )
132            }
133            Self::InvalidTransition { node_id, from, to } => write!(
134                formatter,
135                "invalid status transition for memory node {node_id}: {from} -> {to}"
136            ),
137            Self::InvariantViolation { message } => {
138                write!(formatter, "memory invariant violated: {message}")
139            }
140            Self::Persistence { operation, message } => {
141                write!(
142                    formatter,
143                    "memory persistence {operation} failed: {message}"
144                )
145            }
146        }
147    }
148}
149
150impl std::error::Error for MemoryRepositoryError {}