helios_persistence/search/
errors.rs1use std::fmt;
11
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub enum LoaderError {
17 InvalidResource {
19 message: String,
21 url: Option<String>,
23 },
24
25 MissingField {
27 field: String,
29 url: Option<String>,
31 },
32
33 InvalidExpression {
35 expression: String,
37 error: String,
39 },
40
41 EmbeddedLoadFailed {
43 version: String,
45 message: String,
47 },
48
49 ConfigLoadFailed {
51 path: String,
53 message: String,
55 },
56
57 StorageError {
59 message: String,
61 },
62}
63
64impl fmt::Display for LoaderError {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 LoaderError::InvalidResource { message, url } => {
68 if let Some(url) = url {
69 write!(f, "Invalid SearchParameter '{}': {}", url, message)
70 } else {
71 write!(f, "Invalid SearchParameter: {}", message)
72 }
73 }
74 LoaderError::MissingField { field, url } => {
75 if let Some(url) = url {
76 write!(
77 f,
78 "SearchParameter '{}' missing required field '{}'",
79 url, field
80 )
81 } else {
82 write!(f, "SearchParameter missing required field '{}'", field)
83 }
84 }
85 LoaderError::InvalidExpression { expression, error } => {
86 write!(f, "Invalid FHIRPath expression '{}': {}", expression, error)
87 }
88 LoaderError::EmbeddedLoadFailed { version, message } => {
89 write!(
90 f,
91 "Failed to load embedded {} parameters: {}",
92 version, message
93 )
94 }
95 LoaderError::ConfigLoadFailed { path, message } => {
96 write!(f, "Failed to load config from '{}': {}", path, message)
97 }
98 LoaderError::StorageError { message } => {
99 write!(f, "Storage error loading parameters: {}", message)
100 }
101 }
102 }
103}
104
105impl std::error::Error for LoaderError {}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum RegistryError {
110 DuplicateUrl {
112 url: String,
114 },
115
116 NotFound {
118 identifier: String,
120 },
121
122 InvalidDefinition {
124 message: String,
126 },
127
128 Locked {
130 reason: String,
132 },
133}
134
135impl fmt::Display for RegistryError {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 match self {
138 RegistryError::DuplicateUrl { url } => {
139 write!(f, "SearchParameter with URL '{}' already exists", url)
140 }
141 RegistryError::NotFound { identifier } => {
142 write!(f, "SearchParameter '{}' not found", identifier)
143 }
144 RegistryError::InvalidDefinition { message } => {
145 write!(f, "Invalid SearchParameter definition: {}", message)
146 }
147 RegistryError::Locked { reason } => {
148 write!(f, "Registry is locked: {}", reason)
149 }
150 }
151 }
152}
153
154impl std::error::Error for RegistryError {}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub enum ExtractionError {
159 EvaluationFailed {
161 param_name: String,
163 expression: String,
165 error: String,
167 },
168
169 ConversionFailed {
171 param_name: String,
173 expected_type: String,
175 actual_value: String,
177 },
178
179 UnsupportedType {
181 param_name: String,
183 value_type: String,
185 },
186
187 InvalidResource {
189 message: String,
191 },
192
193 FhirPathError {
195 expression: String,
197 message: String,
199 },
200
201 ConversionError {
203 message: String,
205 },
206}
207
208impl fmt::Display for ExtractionError {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 match self {
211 ExtractionError::EvaluationFailed {
212 param_name,
213 expression,
214 error,
215 } => {
216 write!(
217 f,
218 "Failed to evaluate '{}' for parameter '{}': {}",
219 expression, param_name, error
220 )
221 }
222 ExtractionError::ConversionFailed {
223 param_name,
224 expected_type,
225 actual_value,
226 } => {
227 write!(
228 f,
229 "Cannot convert '{}' to {} for parameter '{}'",
230 actual_value, expected_type, param_name
231 )
232 }
233 ExtractionError::UnsupportedType {
234 param_name,
235 value_type,
236 } => {
237 write!(
238 f,
239 "Unsupported value type '{}' for parameter '{}'",
240 value_type, param_name
241 )
242 }
243 ExtractionError::InvalidResource { message } => {
244 write!(f, "Invalid resource: {}", message)
245 }
246 ExtractionError::FhirPathError {
247 expression,
248 message,
249 } => {
250 write!(f, "FHIRPath error evaluating '{}': {}", expression, message)
251 }
252 ExtractionError::ConversionError { message } => {
253 write!(f, "Conversion error: {}", message)
254 }
255 }
256 }
257}
258
259impl std::error::Error for ExtractionError {}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
263pub enum ReindexError {
264 JobNotFound {
266 job_id: String,
268 },
269
270 AlreadyRunning {
272 existing_job_id: String,
274 },
275
276 ProcessingFailed {
278 resource_type: String,
280 resource_id: String,
282 error: String,
284 },
285
286 StorageError {
288 message: String,
290 },
291
292 Cancelled {
294 job_id: String,
296 },
297}
298
299impl fmt::Display for ReindexError {
300 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301 match self {
302 ReindexError::JobNotFound { job_id } => {
303 write!(f, "Reindex job '{}' not found", job_id)
304 }
305 ReindexError::AlreadyRunning { existing_job_id } => {
306 write!(
307 f,
308 "Reindex already running with job ID '{}'",
309 existing_job_id
310 )
311 }
312 ReindexError::ProcessingFailed {
313 resource_type,
314 resource_id,
315 error,
316 } => {
317 write!(
318 f,
319 "Failed to reindex {}/{}: {}",
320 resource_type, resource_id, error
321 )
322 }
323 ReindexError::StorageError { message } => {
324 write!(f, "Storage error during reindex: {}", message)
325 }
326 ReindexError::Cancelled { job_id } => {
327 write!(f, "Reindex job '{}' was cancelled", job_id)
328 }
329 }
330 }
331}
332
333impl std::error::Error for ReindexError {}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
340 fn test_loader_error_display() {
341 let err = LoaderError::MissingField {
342 field: "expression".to_string(),
343 url: Some("http://example.org/SearchParameter/test".to_string()),
344 };
345 assert!(err.to_string().contains("expression"));
346 assert!(err.to_string().contains("test"));
347 }
348
349 #[test]
350 fn test_registry_error_display() {
351 let err = RegistryError::DuplicateUrl {
352 url: "http://example.org/sp".to_string(),
353 };
354 assert!(err.to_string().contains("already exists"));
355 }
356
357 #[test]
358 fn test_extraction_error_display() {
359 let err = ExtractionError::EvaluationFailed {
360 param_name: "name".to_string(),
361 expression: "Patient.name".to_string(),
362 error: "syntax error".to_string(),
363 };
364 assert!(err.to_string().contains("name"));
365 assert!(err.to_string().contains("Patient.name"));
366 }
367
368 #[test]
369 fn test_reindex_error_display() {
370 let err = ReindexError::ProcessingFailed {
371 resource_type: "Patient".to_string(),
372 resource_id: "123".to_string(),
373 error: "database error".to_string(),
374 };
375 assert!(err.to_string().contains("Patient/123"));
376 }
377}