1use candid::CandidType;
2use derive_more::Display;
3use icydb_core::{
4 db::{query::QueryError, response::ResponseError},
5 error::{ErrorOrigin as CoreErrorOrigin, InternalError},
6 traits::ViewPatchError,
7};
8use serde::{Deserialize, Serialize};
9use thiserror::Error as ThisError;
10
11#[derive(CandidType, Debug, Deserialize, Serialize, ThisError)]
17#[error("{message}")]
18pub struct Error {
19 pub kind: ErrorKind,
20 pub origin: ErrorOrigin,
21 pub message: String,
22}
23
24impl Error {
25 pub fn new(kind: ErrorKind, origin: ErrorOrigin, message: impl Into<String>) -> Self {
26 Self {
27 kind,
28 origin,
29 message: message.into(),
30 }
31 }
32}
33
34impl From<InternalError> for Error {
35 fn from(err: InternalError) -> Self {
36 Self::new(ErrorKind::Internal, err.origin.into(), err.message)
37 }
38}
39
40impl From<QueryError> for Error {
41 fn from(err: QueryError) -> Self {
42 match err {
43 QueryError::Validate(_) | QueryError::Intent(_) | QueryError::Plan(_) => Self::new(
44 ErrorKind::Query(QueryErrorKind::Invalid),
45 ErrorOrigin::Query,
46 err.to_string(),
47 ),
48
49 QueryError::UnsupportedQueryFeature(_) => Self::new(
50 ErrorKind::Query(QueryErrorKind::Unsupported),
51 ErrorOrigin::Query,
52 err.to_string(),
53 ),
54
55 QueryError::Response(ResponseError::NotFound { .. }) => Self::new(
56 ErrorKind::Query(QueryErrorKind::NotFound),
57 ErrorOrigin::Response,
58 err.to_string(),
59 ),
60
61 QueryError::Response(ResponseError::NotUnique { .. }) => Self::new(
62 ErrorKind::Query(QueryErrorKind::NotUnique),
63 ErrorOrigin::Response,
64 err.to_string(),
65 ),
66
67 QueryError::Execute(err) => err.into(),
68 }
69 }
70}
71
72impl From<ResponseError> for Error {
73 fn from(err: ResponseError) -> Self {
74 match err {
75 ResponseError::NotFound { .. } => Self::new(
76 ErrorKind::Query(QueryErrorKind::NotFound),
77 ErrorOrigin::Query,
78 err.to_string(),
79 ),
80
81 ResponseError::NotUnique { .. } => Self::new(
82 ErrorKind::Query(QueryErrorKind::NotUnique),
83 ErrorOrigin::Query,
84 err.to_string(),
85 ),
86 }
87 }
88}
89
90#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
96pub enum ErrorKind {
97 Query(QueryErrorKind),
98 Update(UpdateErrorKind),
99 Store(StoreErrorKind),
100
101 Internal,
103}
104
105#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
110pub enum QueryErrorKind {
111 Invalid,
113
114 Unsupported,
116
117 UnorderedPagination,
119
120 NotFound,
122
123 NotUnique,
125}
126
127#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
132pub enum UpdateErrorKind {
133 Patch(PatchError),
135
136 NotFound,
138
139 ConstraintViolation,
141
142 Conflict,
144}
145
146#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
151pub enum PatchError {
152 InvalidShape,
153 MissingKey,
154 CardinalityViolation,
155}
156
157impl From<ViewPatchError> for PatchError {
158 fn from(err: ViewPatchError) -> Self {
159 match err {
160 ViewPatchError::InvalidShape { .. } => Self::InvalidShape,
161 ViewPatchError::MissingKey { .. } => Self::MissingKey,
162 ViewPatchError::CardinalityViolation { .. } => Self::CardinalityViolation,
163 ViewPatchError::Context { source, .. } => (*source).into(),
164 }
165 }
166}
167
168#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
173pub enum StoreErrorKind {
174 NotFound,
175 Unavailable,
176}
177
178#[derive(CandidType, Clone, Copy, Debug, Deserialize, Display, Eq, PartialEq, Serialize)]
184pub enum ErrorOrigin {
185 Executor,
186 Index,
187 Interface,
188 Query,
189 Response,
190 Serialize,
191 Store,
192}
193
194impl From<CoreErrorOrigin> for ErrorOrigin {
195 fn from(origin: CoreErrorOrigin) -> Self {
196 match origin {
197 CoreErrorOrigin::Executor => Self::Executor,
198 CoreErrorOrigin::Index => Self::Index,
199 CoreErrorOrigin::Interface => Self::Interface,
200 CoreErrorOrigin::Query => Self::Query,
201 CoreErrorOrigin::Response => Self::Response,
202 CoreErrorOrigin::Serialize => Self::Serialize,
203 CoreErrorOrigin::Store => Self::Store,
204 }
205 }
206}