nautilus_protocol/
error.rs1use thiserror::Error;
12
13use crate::wire::RpcError;
14
15pub const ERR_SCHEMA_VALIDATION: i32 = 1000;
19pub const ERR_INVALID_MODEL: i32 = 1001;
20pub const ERR_INVALID_FIELD: i32 = 1002;
21pub const ERR_TYPE_MISMATCH: i32 = 1003;
22
23pub const ERR_QUERY_PLANNING: i32 = 2000;
25pub const ERR_INVALID_FILTER: i32 = 2001;
26pub const ERR_INVALID_ORDERBY: i32 = 2002;
27pub const ERR_UNSUPPORTED_OPERATION: i32 = 2003;
28
29pub const ERR_DATABASE_EXECUTION: i32 = 3000;
31pub const ERR_CONNECTION_FAILED: i32 = 3001;
32pub const ERR_CONSTRAINT_VIOLATION: i32 = 3002;
33pub const ERR_QUERY_TIMEOUT: i32 = 3003;
34pub const ERR_RECORD_NOT_FOUND: i32 = 3004;
35pub const ERR_UNIQUE_CONSTRAINT: i32 = 3005;
36pub const ERR_FOREIGN_KEY_CONSTRAINT: i32 = 3006;
37pub const ERR_CHECK_CONSTRAINT: i32 = 3007;
38pub const ERR_NULL_CONSTRAINT: i32 = 3008;
39pub const ERR_DEADLOCK: i32 = 3009;
40pub const ERR_SERIALIZATION_FAILURE: i32 = 3010;
41
42pub const ERR_TRANSACTION_NOT_FOUND: i32 = 4001;
44pub const ERR_TRANSACTION_TIMEOUT: i32 = 4002;
45pub const ERR_TRANSACTION_ALREADY_CLOSED: i32 = 4003;
46pub const ERR_TRANSACTION_FAILED: i32 = 4004;
47
48pub const ERR_INTERNAL: i32 = 9000;
50pub const ERR_UNSUPPORTED_PROTOCOL_VERSION: i32 = 9001;
51pub const ERR_INVALID_METHOD: i32 = 9002;
52pub const ERR_INVALID_REQUEST_PARAMS: i32 = 9003;
53
54#[derive(Debug, Error)]
56pub enum ProtocolError {
57 #[error("Schema validation error: {0}")]
58 SchemaValidation(String),
59
60 #[error("Invalid model: {0}")]
61 InvalidModel(String),
62
63 #[error("Invalid field: {0}")]
64 InvalidField(String),
65
66 #[error("Type mismatch: {0}")]
67 TypeMismatch(String),
68
69 #[error("Query planning error: {0}")]
70 QueryPlanning(String),
71
72 #[error("Invalid filter: {0}")]
73 InvalidFilter(String),
74
75 #[error("Invalid order by: {0}")]
76 InvalidOrderBy(String),
77
78 #[error("Unsupported operation: {0}")]
79 UnsupportedOperation(String),
80
81 #[error("Database execution error: {0}")]
82 DatabaseExecution(String),
83
84 #[error("Connection failed: {0}")]
85 ConnectionFailed(String),
86
87 #[error("Constraint violation: {0}")]
88 ConstraintViolation(String),
89
90 #[error("Unique constraint violation: {0}")]
91 UniqueConstraintViolation(String),
92
93 #[error("Foreign key constraint violation: {0}")]
94 ForeignKeyConstraintViolation(String),
95
96 #[error("Check constraint violation: {0}")]
97 CheckConstraintViolation(String),
98
99 #[error("NOT NULL constraint violation: {0}")]
100 NullConstraintViolation(String),
101
102 #[error("Deadlock detected: {0}")]
103 Deadlock(String),
104
105 #[error("Serialization failure: {0}")]
106 SerializationFailure(String),
107
108 #[error("Query timeout: {0}")]
109 QueryTimeout(String),
110
111 #[error("Record not found: {0}")]
112 RecordNotFound(String),
113
114 #[error("Transaction not found: {0}")]
115 TransactionNotFound(String),
116
117 #[error("Transaction timed out: {0}")]
118 TransactionTimeout(String),
119
120 #[error("Transaction already closed: {0}")]
121 TransactionAlreadyClosed(String),
122
123 #[error("Transaction failed: {0}")]
124 TransactionFailed(String),
125
126 #[error("Internal engine error: {0}")]
127 Internal(String),
128
129 #[error("Unsupported protocol version: {actual}, expected {expected}")]
130 UnsupportedProtocolVersion { actual: u32, expected: u32 },
131
132 #[error("Invalid method: {0}")]
133 InvalidMethod(String),
134
135 #[error("Invalid request params: {0}")]
136 InvalidParams(String),
137
138 #[error("Serialization error: {0}")]
139 Serialization(String),
140}
141
142impl ProtocolError {
143 pub fn code(&self) -> i32 {
145 match self {
146 ProtocolError::SchemaValidation(_) => ERR_SCHEMA_VALIDATION,
147 ProtocolError::InvalidModel(_) => ERR_INVALID_MODEL,
148 ProtocolError::InvalidField(_) => ERR_INVALID_FIELD,
149 ProtocolError::TypeMismatch(_) => ERR_TYPE_MISMATCH,
150 ProtocolError::QueryPlanning(_) => ERR_QUERY_PLANNING,
151 ProtocolError::InvalidFilter(_) => ERR_INVALID_FILTER,
152 ProtocolError::InvalidOrderBy(_) => ERR_INVALID_ORDERBY,
153 ProtocolError::UnsupportedOperation(_) => ERR_UNSUPPORTED_OPERATION,
154 ProtocolError::DatabaseExecution(_) => ERR_DATABASE_EXECUTION,
155 ProtocolError::ConnectionFailed(_) => ERR_CONNECTION_FAILED,
156 ProtocolError::ConstraintViolation(_) => ERR_CONSTRAINT_VIOLATION,
157 ProtocolError::UniqueConstraintViolation(_) => ERR_UNIQUE_CONSTRAINT,
158 ProtocolError::ForeignKeyConstraintViolation(_) => ERR_FOREIGN_KEY_CONSTRAINT,
159 ProtocolError::CheckConstraintViolation(_) => ERR_CHECK_CONSTRAINT,
160 ProtocolError::NullConstraintViolation(_) => ERR_NULL_CONSTRAINT,
161 ProtocolError::Deadlock(_) => ERR_DEADLOCK,
162 ProtocolError::SerializationFailure(_) => ERR_SERIALIZATION_FAILURE,
163 ProtocolError::QueryTimeout(_) => ERR_QUERY_TIMEOUT,
164 ProtocolError::RecordNotFound(_) => ERR_RECORD_NOT_FOUND,
165 ProtocolError::TransactionNotFound(_) => ERR_TRANSACTION_NOT_FOUND,
166 ProtocolError::TransactionTimeout(_) => ERR_TRANSACTION_TIMEOUT,
167 ProtocolError::TransactionAlreadyClosed(_) => ERR_TRANSACTION_ALREADY_CLOSED,
168 ProtocolError::TransactionFailed(_) => ERR_TRANSACTION_FAILED,
169 ProtocolError::Internal(_) => ERR_INTERNAL,
170 ProtocolError::UnsupportedProtocolVersion { .. } => ERR_UNSUPPORTED_PROTOCOL_VERSION,
171 ProtocolError::InvalidMethod(_) => ERR_INVALID_METHOD,
172 ProtocolError::InvalidParams(_) => ERR_INVALID_REQUEST_PARAMS,
173 ProtocolError::Serialization(_) => ERR_INTERNAL,
174 }
175 }
176}
177
178impl From<ProtocolError> for RpcError {
179 fn from(err: ProtocolError) -> Self {
180 RpcError {
181 code: err.code(),
182 message: err.to_string(),
183 data: None,
184 }
185 }
186}
187
188impl From<serde_json::Error> for ProtocolError {
189 fn from(err: serde_json::Error) -> Self {
190 ProtocolError::Serialization(err.to_string())
191 }
192}
193
194pub type Result<T> = std::result::Result<T, ProtocolError>;
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200 use serde_json::Value;
201
202 #[test]
203 fn test_error_codes() {
204 assert_eq!(
205 ProtocolError::SchemaValidation("test".into()).code(),
206 ERR_SCHEMA_VALIDATION
207 );
208 assert_eq!(
209 ProtocolError::InvalidModel("User".into()).code(),
210 ERR_INVALID_MODEL
211 );
212 assert_eq!(
213 ProtocolError::QueryPlanning("bad query".into()).code(),
214 ERR_QUERY_PLANNING
215 );
216 assert_eq!(
217 ProtocolError::DatabaseExecution("timeout".into()).code(),
218 ERR_DATABASE_EXECUTION
219 );
220 assert_eq!(
221 ProtocolError::UnsupportedProtocolVersion {
222 actual: 2,
223 expected: 1
224 }
225 .code(),
226 ERR_UNSUPPORTED_PROTOCOL_VERSION
227 );
228 }
229
230 #[test]
231 fn test_error_to_rpc_error() {
232 let err = ProtocolError::InvalidModel("Post".to_string());
233 let rpc_err: RpcError = err.into();
234
235 assert_eq!(rpc_err.code, ERR_INVALID_MODEL);
236 assert_eq!(rpc_err.message, "Invalid model: Post");
237 assert!(rpc_err.data.is_none());
238 }
239
240 #[test]
241 fn test_error_display() {
242 let err = ProtocolError::UnsupportedProtocolVersion {
243 actual: 3,
244 expected: 1,
245 };
246 assert_eq!(
247 err.to_string(),
248 "Unsupported protocol version: 3, expected 1"
249 );
250 }
251
252 #[test]
253 fn test_serde_error_conversion() {
254 let bad_json = "{invalid json}";
255 let err: serde_json::Error = serde_json::from_str::<Value>(bad_json).unwrap_err();
256 let protocol_err: ProtocolError = err.into();
257
258 match protocol_err {
259 ProtocolError::Serialization(msg) => {
260 assert!(!msg.is_empty());
261 }
262 _ => panic!("Expected Serialization error"),
263 }
264 }
265}