Error handling refactor
This refactor aims to improve error handling throughout the project by refining the overarching error types and increasing usage of proper error handling. Replaced existing networked operation error with `NetworkOperationError`. `NetworkOperationError` does not forward any internal error details, which allows `OperationError` to grow into a better error type. `OperationError` now has support for storing real typed errors inside of it for better debugging. `IntoInternalError` is a trait which allows for easy conversion of error types into `OperationError::internal`.
parent: tbd commit: e02c03d
1 | use ; |
2 | |
3 | use Context; |
4 | use FutureExt; |
5 | use |
6 | , | AuthenticatedPayload
7 | , |
8 | , | Instance
9 | , | GiteratedMessage
10 | |
11 | AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, |
12 | , |
13 | , | ObjectBackend
14 | , |
15 | , |
16 | , |
17 | ; |
18 | |
19 | use trace; |
20 | |
21 | use crate:: |
22 | GiteratedOperationHandler, ObjectMeta, ObjectOperationPair, ObjectValuePair, OperationMeta, |
23 | OperationWrapper, SettingMeta, StackOperationState, ValueMeta, |
24 | ; |
25 | |
26 | /// Temporary name for the next generation of Giterated stack |
27 | |
28 | |
29 | operation_handlers: , |
30 | value_getters: , |
31 | setting_getters: , |
32 | metadata: RuntimeMetadata, |
33 | |
34 | |
35 | |
36 | |
37 | &mut self, |
38 | builder: , |
39 | |
40 | for in builder.operation_handlers |
41 | let tree = self.get_or_create_tree; |
42 | |
43 | tree.push; |
44 | |
45 | |
46 | for in builder.value_getters |
47 | assert!; |
48 | |
49 | |
50 | for in builder.setting_getters |
51 | assert!; |
52 | |
53 | |
54 | self.metadata.append; |
55 | |
56 | self |
57 | |
58 | |
59 | |
60 | if self.operation_handlers.contains_key |
61 | self.operation_handlers.get_mut .unwrap |
62 | else |
63 | self.operation_handlers |
64 | .insert; |
65 | |
66 | self.operation_handlers.get_mut .unwrap |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | elements: , |
73 | |
74 | |
75 | |
76 | |
77 | Self |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | self.elements.push; |
84 | |
85 | |
86 | pub async |
87 | &self, |
88 | object: & , |
89 | operation: & , |
90 | operation_state: &StackOperationState, |
91 | |
92 | for handler in self.elements.iter |
93 | match handler.handle .await |
94 | Ok => return Ok, |
95 | Err => match err |
96 | => | Operation
97 | return Err |
98 | |
99 | => return Err, | Internal
100 | _ => |
101 | continue; |
102 | |
103 | , |
104 | |
105 | |
106 | |
107 | Err |
108 | |
109 | |
110 | |
111 | /// Stores runtime metadata for all in-use Giterated protocol types. |
112 | |
113 | |
114 | objects: , |
115 | operations: , |
116 | values: , |
117 | settings: , |
118 | |
119 | |
120 | /// Defines a type that is a valid Giterated runtime state. |
121 | /// |
122 | /// This allows for extraction of state in handlers, based on a |
123 | /// [`FromOperationState<S>`] impl on (what is in this case) [`Self`]. |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | operation_handlers: , |
130 | value_getters: , |
131 | setting_getters: , |
132 | metadata: RuntimeMetadata, |
133 | state: S, |
134 | |
135 | |
136 | |
137 | |
138 | Self |
139 | operation_handlers: Default default, |
140 | value_getters: Default default, |
141 | setting_getters: Default default, |
142 | metadata: Default default, |
143 | state, |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | /// Insert an operation handler into the runtime builder. |
150 | /// |
151 | /// # Type Registration |
152 | /// Inserting the handler will automatically, if required, register the operation type of the |
153 | /// handler. It will **not** register the object type automatically. |
154 | |
155 | |
156 | O: GiteratedObject + 'static, |
157 | D: + 'static + Clone, |
158 | H: + 'static + Clone + Send + Sync, |
159 | : Send + Sync, | Failure
160 | : Send + Sync, | Success
161 | |
162 | let object_name = handler.object_name .to_string; |
163 | let operation_name = handler.operation_name .to_string; |
164 | |
165 | let wrapped = new; |
166 | |
167 | let pair = ObjectOperationPair |
168 | object_name, |
169 | operation_name, |
170 | ; |
171 | |
172 | self.operation_handlers.insert; |
173 | |
174 | self.metadata.; |
175 | |
176 | self |
177 | |
178 | |
179 | /// Register a [`GiteratedObject`] type with the runtime. |
180 | /// |
181 | /// # Type Registration |
182 | /// This will register the provided object type. |
183 | |
184 | self.metadata.; |
185 | |
186 | // Insert handler so ObjectRequest is handled properly |
187 | let handler = move |_object: &Instance, |
188 | operation: ObjectRequest, |
189 | _state: S, |
190 | _operation_state: StackOperationState, |
191 | stack: | |
192 | async move |
193 | for in stack.metadata.objects.iter |
194 | if .is_ok |
195 | return Ok; |
196 | |
197 | |
198 | |
199 | Err |
200 | |
201 | .boxed_local |
202 | ; |
203 | |
204 | self.operation; |
205 | |
206 | self |
207 | |
208 | |
209 | /// Register a [`Setting`] type with the runtime. |
210 | /// |
211 | /// # Type Registration |
212 | /// This will register the provided setting type. |
213 | |
214 | self.metadata.; |
215 | |
216 | self |
217 | |
218 | |
219 | /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing |
220 | /// its associated handler for [`GetValue`]. |
221 | /// |
222 | /// # Type Registration |
223 | /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified |
224 | /// object type. It will **not** register the object type automatically. |
225 | |
226 | |
227 | O: GiteratedObject + 'static, |
228 | V: + 'static + Clone, |
229 | F: + Clone + 'static + Send + Sync, |
230 | |
231 | let object_name = handler.object_name .to_string; |
232 | let value_name = value_name .to_string; |
233 | |
234 | let wrapped = new; |
235 | |
236 | let handler_object_name = object_name.clone; |
237 | let handler_value_name = value_name.clone; |
238 | |
239 | // Insert handler so GetValue is handled properly |
240 | let _handler = move |object: &O, |
241 | operation: , |
242 | _state: S, |
243 | operation_state: StackOperationState, |
244 | stack: | |
245 | let stack = stack.clone; |
246 | let object_name = handler_object_name; |
247 | let value_name = handler_value_name; |
248 | let object = object.clone; |
249 | async move |
250 | for in stack.value_getters.iter |
251 | if target.object_kind != object_name |
252 | continue; |
253 | |
254 | |
255 | if target.value_kind != value_name |
256 | continue; |
257 | |
258 | |
259 | return match getter |
260 | .handle |
261 | &, |
262 | & |
263 | value_name: operation.value_name, |
264 | ty: Default default, |
265 | as , |
266 | &operation_state, |
267 | |
268 | .await |
269 | Ok => Ok, |
270 | Err => Err |
271 | => Operation, | Operation
272 | => Internal, | Internal
273 | => Unhandled, | Unhandled
274 | , |
275 | |
276 | |
277 | |
278 | Err |
279 | |
280 | .boxed_local |
281 | ; |
282 | |
283 | assert! |
284 | .value_getters |
285 | .insert |
286 | ObjectValuePair |
287 | object_kind: object_name, |
288 | value_kind: value_name |
289 | , |
290 | wrapped |
291 | |
292 | .is_none; |
293 | |
294 | self.metadata.; |
295 | |
296 | self |
297 | |
298 | |
299 | /// Register a handler for [`GetSetting`] for it's associated object type. |
300 | |
301 | |
302 | O: GiteratedObject + 'static, |
303 | F: + Clone + 'static + Send + Sync, |
304 | |
305 | let object_name = handler.object_name .to_string; |
306 | |
307 | let wrapped = new; |
308 | |
309 | assert!; |
310 | |
311 | self |
312 | |
313 | |
314 | |
315 | |
316 | |
317 | let object_name = object_name .to_string; |
318 | |
319 | let object_meta = ; |
320 | |
321 | if self.objects.insert .is_some |
322 | trace! |
323 | "Registration of object {} overwrote previous registration.", |
324 | object_name |
325 | ; |
326 | else |
327 | trace! |
328 | |
329 | |
330 | |
331 | |
332 | &mut self, |
333 | |
334 | let object_name = object_name .to_string; |
335 | let operation_name = operation_name .to_string; |
336 | |
337 | if self |
338 | .operations |
339 | .insert |
340 | ObjectOperationPair |
341 | object_name: object_name.clone, |
342 | operation_name: operation_name.clone, |
343 | , |
344 | , |
345 | |
346 | .is_some |
347 | |
348 | trace! |
349 | "Registration of object operation {}<{}> overwrote previous registration.", |
350 | , | operation_name
351 | object_name |
352 | ; |
353 | else |
354 | trace! |
355 | "Registration of object operation {}<{}>.", |
356 | , | operation_name
357 | object_name |
358 | |
359 | |
360 | |
361 | |
362 | |
363 | O: GiteratedObject + 'static, |
364 | V: + 'static, |
365 | > |
366 | &mut self, |
367 | |
368 | let object_name = object_name .to_string; |
369 | let value_name = value_name .to_string; |
370 | |
371 | if self |
372 | .values |
373 | .insert |
374 | ObjectValuePair |
375 | object_kind: object_name.clone, |
376 | value_kind: value_name.clone, |
377 | , |
378 | , |
379 | |
380 | .is_some |
381 | |
382 | trace! |
383 | "Registration of value <{}>::{} overwrote previous registration.", |
384 | , | object_name
385 | value_name |
386 | ; |
387 | else |
388 | trace! |
389 | "Registration of value <{}>::{}.", |
390 | , | object_name
391 | value_name |
392 | ; |
393 | |
394 | |
395 | |
396 | |
397 | let setting_name = name .to_string; |
398 | |
399 | if self |
400 | .settings |
401 | .insert |
402 | .is_some |
403 | |
404 | trace! |
405 | "Registration of setting {} overwrote previous registration.", |
406 | name |
407 | ; |
408 | else |
409 | trace!; |
410 | |
411 | |
412 | |
413 | |
414 | self.objects.extend; |
415 | self.operations.extend; |
416 | self.values.extend; |
417 | self.settings.extend; |
418 | |
419 | |
420 | |
421 | /// Handles a giterated network message, returning either a raw success |
422 | /// payload or a serialized error payload. |
423 | pub async |
424 | &self, |
425 | message: AuthenticatedPayload, |
426 | operation_state: &StackOperationState, |
427 | |
428 | let message: = message.into_message; |
429 | |
430 | // Deserialize the object, also getting the object type's name |
431 | let = |
432 | let mut result = None; |
433 | |
434 | for in self.metadata.objects.iter |
435 | if let Ok = |
436 | result = Some; |
437 | break; |
438 | |
439 | |
440 | |
441 | result |
442 | |
443 | .ok_or_else?; |
444 | |
445 | trace! |
446 | "Handling network message {}::<{}>", |
447 | message.operation, |
448 | object_type |
449 | ; |
450 | |
451 | if message.operation == "get_value" |
452 | // Special case |
453 | let operation: GetValue = from_slice .unwrap; |
454 | |
455 | let result = self |
456 | .network_get_value |
457 | object, |
458 | object_type.clone, |
459 | operation.clone, |
460 | operation_state, |
461 | |
462 | .await; |
463 | |
464 | // In the case of internal errors, attach context |
465 | let result = result.map_err |
466 | => Operation, | Operation
467 | => | Internal
468 | Internal |
469 | "{}::get_value::<{}> outcome" |
470 | object_type, operation.value_name |
471 | ) |
472 | |
473 | => Unhandled, | Unhandled
474 | ; |
475 | |
476 | return result; |
477 | else if message.operation == "get_setting" |
478 | let operation: GetSetting = from_slice .unwrap; |
479 | let setting_meta = self |
480 | .metadata |
481 | .settings |
482 | .get |
483 | .ok_or_else?; |
484 | let raw_result = self |
485 | .get_setting |
486 | .await; |
487 | return match raw_result |
488 | Ok => |
489 | // Success is the setting type, serialize it |
490 | let serialized = .unwrap; |
491 | |
492 | Ok |
493 | |
494 | Err => Err |
495 | => | Operation
496 | // We know how to resolve this type |
497 | let failure: GetSettingError = *failure.downcast .unwrap; |
498 | |
499 | Operation |
500 | |
501 | => | Internal
502 | Internal |
503 | "{}::get_setting::<{}> handler outcome" |
504 | object_type, setting_meta.name |
505 | ) |
506 | |
507 | => Unhandled, | Unhandled
508 | , |
509 | ; |
510 | |
511 | |
512 | let target = ObjectOperationPair |
513 | object_name: object_type.clone, |
514 | operation_name: message.operation.clone, |
515 | ; |
516 | |
517 | // Resolve the target operations from the handlers table |
518 | let handler = self |
519 | .operation_handlers |
520 | .get |
521 | .ok_or_else?; |
522 | |
523 | trace! |
524 | "Resolved operation handler for network message {}::<{}>", |
525 | message.operation, |
526 | object_type |
527 | ; |
528 | |
529 | // Deserialize the operation |
530 | let meta = self |
531 | .metadata |
532 | .operations |
533 | .get |
534 | .ok_or_else?; |
535 | |
536 | let operation = |
537 | as_internal_error_with_context | .
538 | "deserializing operation {}::{}" |
539 | target.object_name, target.operation_name |
540 | )?; |
541 | |
542 | trace! |
543 | "Deserialized operation for network message {}::<{}>", |
544 | message.operation, |
545 | object_type |
546 | ; |
547 | |
548 | trace! |
549 | "Calling handler for network message {}::<{}>", |
550 | message.operation, |
551 | object_type |
552 | ; |
553 | |
554 | // Get the raw result of the operation, where the return values are boxed. |
555 | let raw_result = handler.handle .await; |
556 | |
557 | trace! |
558 | "Finished handling network message {}::<{}>", |
559 | message.operation, |
560 | object_type |
561 | ; |
562 | |
563 | // Deserialize the raw result for the network |
564 | match raw_result |
565 | Ok => Ok, |
566 | Err => Err |
567 | => | Operation
568 | Operation |
569 | |
570 | => | Internal
571 | Internal |
572 | "operation {}::{} handler outcome" |
573 | target.object_name, target.operation_name |
574 | ) |
575 | |
576 | => Unhandled, | Unhandled
577 | , |
578 | |
579 | |
580 | |
581 | pub async |
582 | &self, |
583 | object: , |
584 | object_kind: String, |
585 | operation: GetValue, |
586 | operation_state: &StackOperationState, |
587 | |
588 | trace!; |
589 | |
590 | let value_meta = self |
591 | .metadata |
592 | .values |
593 | .get |
594 | object_kind: object_kind.clone, |
595 | value_kind: operation.value_name.clone, |
596 | |
597 | .ok_or_else?; |
598 | |
599 | for in self.value_getters.iter |
600 | if target.object_kind != object_kind |
601 | continue; |
602 | |
603 | |
604 | if target.value_kind != operation.value_name |
605 | continue; |
606 | |
607 | |
608 | return match getter |
609 | .handle |
610 | .await |
611 | |
612 | Ok => |
613 | // Serialize success, which is the value type itself |
614 | let serialized = .as_internal_error?; |
615 | |
616 | Ok |
617 | |
618 | Err => Err |
619 | => | Operation
620 | // Failure is sourced from GetValue operation, but this is hardcoded for now |
621 | let failure: GetValueError = *failure.downcast .unwrap; |
622 | |
623 | Operation |
624 | |
625 | => Internal, | Internal
626 | => Unhandled, | Unhandled
627 | , |
628 | ; |
629 | |
630 | |
631 | Err |
632 | |
633 | |
634 | pub async |
635 | &self, |
636 | object: , |
637 | object_kind: String, |
638 | operation: GetSetting, |
639 | operation_state: &StackOperationState, |
640 | |
641 | trace! |
642 | "Handling network {}::get_setting for {}", |
643 | object_kind, |
644 | operation.setting_name |
645 | ; |
646 | |
647 | let setting_getter = self |
648 | .setting_getters |
649 | .get |
650 | .ok_or_else?; |
651 | |
652 | setting_getter |
653 | .handle |
654 | .await |
655 | |
656 | |
657 | pub async |
658 | &self, |
659 | _operation: SetSetting, |
660 | _operation_state: &StackOperationState, |
661 | |
662 | todo! |
663 | |
664 | |
665 | |
666 | use Debug; |
667 | |
668 | |
669 | |
670 | async |
671 | &self, |
672 | in_object: O, |
673 | operation_name: &str, |
674 | payload: D, |
675 | operation_state: &StackOperationState, |
676 | |
677 | |
678 | O: GiteratedObject + Debug + 'static, |
679 | D: + Debug + 'static, |
680 | |
681 | // Erase object and operation types. |
682 | let object = Box new as ; |
683 | let operation = Box new as ; |
684 | |
685 | // We need to hijack get_value, set_setting, and get_setting. |
686 | if operation_name == "get_value" |
687 | let mut value_meta = None; |
688 | for in self.metadata.values.iter |
689 | if |
690 | value_meta = Some; |
691 | break; |
692 | |
693 | |
694 | |
695 | let value_meta = value_meta.ok_or_else?; |
696 | |
697 | let value_name = value_meta.name.clone; |
698 | |
699 | trace! |
700 | "Handling get_value for {}::{}", |
701 | , | object_name
702 | value_name |
703 | ; |
704 | |
705 | for in self.value_getters.iter |
706 | if target.object_kind != object_name |
707 | continue; |
708 | |
709 | |
710 | if target.value_kind != value_name |
711 | continue; |
712 | |
713 | |
714 | return match getter |
715 | .handle |
716 | .await |
717 | |
718 | Ok => Ok, |
719 | Err => Err |
720 | => | Operation
721 | Operation |
722 | |
723 | => | Internal
724 | Internal |
725 | "{}::get_value::<{}> handler outcome" |
726 | , | object_name
727 | value_name |
728 | ) |
729 | |
730 | => Unhandled, | Unhandled
731 | , |
732 | ; |
733 | |
734 | |
735 | return Err; |
736 | else if operation. |
737 | let get_setting: = operation.downcast .unwrap; |
738 | let setting_name = get_setting.setting_name.clone; |
739 | |
740 | let raw_result = self |
741 | .get_setting |
742 | object, |
743 | to_string, | object_name .
744 | *get_setting, |
745 | operation_state, |
746 | |
747 | .await; |
748 | |
749 | return match raw_result |
750 | Ok => |
751 | // Success is the setting type, serialize it |
752 | // let serialized = (setting_meta.serialize)(success).unwrap(); |
753 | |
754 | // Ok(serde_json::to_vec(&serialized).unwrap()) |
755 | Ok |
756 | |
757 | Err => Err |
758 | => | Operation
759 | // We know this is the right type |
760 | Operation |
761 | |
762 | => | Internal
763 | Internal |
764 | "{}::get_setting::<{}> handler outcome" |
765 | , | object_name
766 | setting_name |
767 | ) |
768 | |
769 | => Unhandled, | Unhandled
770 | , |
771 | ; |
772 | else if operation. |
773 | todo! |
774 | else if operation. |
775 | todo! |
776 | |
777 | |
778 | // Resolve the operation from the known operations table. |
779 | let operation_type = |
780 | let mut operation_type = None; |
781 | |
782 | for in self.metadata.operations.iter |
783 | // Skip elements that we know will not match |
784 | if target.object_name != object_name |
785 | continue; |
786 | |
787 | |
788 | if target.operation_name != operation_name |
789 | continue; |
790 | |
791 | |
792 | if |
793 | operation_type = Some; |
794 | break; |
795 | |
796 | |
797 | |
798 | operation_type |
799 | |
800 | .ok_or_else?; |
801 | |
802 | // Resolve the handler from our handler tree |
803 | let handler_tree = self |
804 | .operation_handlers |
805 | .get |
806 | .ok_or_else?; |
807 | |
808 | let raw_result = handler_tree |
809 | .handle |
810 | .await; |
811 | |
812 | // Convert the dynamic result back into its concrete type |
813 | match raw_result |
814 | Ok => Ok, |
815 | Err => Err |
816 | => | Internal
817 | Internal |
818 | "operation {}::{} handler outcome" |
819 | operation_type.object_name, operation_type.operation_name |
820 | ) |
821 | |
822 | => | Operation
823 | Operation |
824 | |
825 | => Unhandled, | Unhandled
826 | , |
827 | |
828 | |
829 | |
830 | async |
831 | &self, |
832 | object_str: &str, |
833 | _operation_state: &StackOperationState, |
834 | |
835 | // TODO: Authorization? |
836 | for in self.metadata.objects.iter |
837 | if let Ok = |
838 | return Ok |
839 | new_unchecked |
840 | ; |
841 | |
842 | |
843 | |
844 | Err |
845 | |
846 | |
847 |