1use std::fmt;
2
3#[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 {}