JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

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`.

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨e02c03d

⁨giterated-stack/src/handler.rs⁩ - ⁨29799⁩ bytes
Raw
1 use std::{any::Any, collections::HashMap, sync::Arc};
2
3 use anyhow::Context;
4 use futures_util::FutureExt;
5 use giterated_models::{
6 authenticated::AuthenticatedPayload,
7 error::{GetValueError, IntoInternalError, OperationError},
8 instance::Instance,
9 message::GiteratedMessage,
10 object::{
11 AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse,
12 },
13 object_backend::ObjectBackend,
14 operation::{AnyOperation, GiteratedOperation},
15 settings::{GetSetting, GetSettingError, SetSetting, Setting},
16 value::{AnyValue, GetValue, GetValueTyped, GiteratedObjectValue},
17 };
18
19 use tracing::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 #[derive(Default)]
28 pub struct GiteratedStack {
29 operation_handlers: HashMap<ObjectOperationPair, HandlerTree>,
30 value_getters: HashMap<ObjectValuePair, OperationWrapper>,
31 setting_getters: HashMap<String, OperationWrapper>,
32 metadata: RuntimeMetadata,
33 }
34
35 impl GiteratedStack {
36 pub fn merge_builder<S: GiteratedStackState>(
37 &mut self,
38 builder: SubstackBuilder<S>,
39 ) -> &mut Self {
40 for (target, handler) in builder.operation_handlers {
41 let tree = self.get_or_create_tree(&target);
42
43 tree.push(handler);
44 }
45
46 for (target, handler) in builder.value_getters {
47 assert!(self.value_getters.insert(target, handler).is_none());
48 }
49
50 for (target, handler) in builder.setting_getters {
51 assert!(self.setting_getters.insert(target, handler).is_none());
52 }
53
54 self.metadata.append(builder.metadata);
55
56 self
57 }
58
59 fn get_or_create_tree(&mut self, target: &ObjectOperationPair) -> &mut HandlerTree {
60 if self.operation_handlers.contains_key(target) {
61 self.operation_handlers.get_mut(target).unwrap()
62 } else {
63 self.operation_handlers
64 .insert(target.clone(), HandlerTree::default());
65
66 self.operation_handlers.get_mut(target).unwrap()
67 }
68 }
69 }
70
71 pub struct HandlerTree {
72 elements: Vec<OperationWrapper>,
73 }
74
75 impl Default for HandlerTree {
76 fn default() -> Self {
77 Self { elements: vec![] }
78 }
79 }
80
81 impl HandlerTree {
82 pub fn push(&mut self, handler: OperationWrapper) {
83 self.elements.push(handler);
84 }
85
86 pub async fn handle(
87 &self,
88 object: &Box<dyn Any + Send + Sync>,
89 operation: &Box<dyn Any + Send + Sync>,
90 operation_state: &StackOperationState,
91 ) -> Result<Box<dyn Any + 'static>, OperationError<Box<dyn Any + 'static>>> {
92 for handler in self.elements.iter() {
93 match handler.handle(object, &operation, operation_state).await {
94 Ok(success) => return Ok(success),
95 Err(err) => match err {
96 OperationError::Operation(failure) => {
97 return Err(OperationError::Operation(failure))
98 }
99 OperationError::Internal(e) => return Err(OperationError::Internal(e)),
100 _ => {
101 continue;
102 }
103 },
104 }
105 }
106
107 Err(OperationError::Unhandled)
108 }
109 }
110
111 /// Stores runtime metadata for all in-use Giterated protocol types.
112 #[derive(Default)]
113 struct RuntimeMetadata {
114 objects: HashMap<String, ObjectMeta>,
115 operations: HashMap<ObjectOperationPair, OperationMeta>,
116 values: HashMap<ObjectValuePair, ValueMeta>,
117 settings: HashMap<String, SettingMeta>,
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 pub trait GiteratedStackState: Send + Sync + Clone {}
125
126 impl<T: Send + Sync + Clone> GiteratedStackState for T {}
127
128 pub struct SubstackBuilder<S: GiteratedStackState> {
129 operation_handlers: HashMap<ObjectOperationPair, OperationWrapper>,
130 value_getters: HashMap<ObjectValuePair, OperationWrapper>,
131 setting_getters: HashMap<String, OperationWrapper>,
132 metadata: RuntimeMetadata,
133 state: S,
134 }
135
136 impl<S: GiteratedStackState + 'static> SubstackBuilder<S> {
137 pub fn new(state: S) -> Self {
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 impl<S: GiteratedStackState + 'static> SubstackBuilder<S> {
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 pub fn operation<A, O, D, H>(&mut self, handler: H) -> &mut Self
155 where
156 O: GiteratedObject + 'static,
157 D: GiteratedOperation<O> + 'static + Clone,
158 H: GiteratedOperationHandler<A, O, D, S> + 'static + Clone + Send + Sync,
159 D::Failure: Send + Sync,
160 D::Success: Send + Sync,
161 {
162 let object_name = handler.object_name().to_string();
163 let operation_name = handler.operation_name().to_string();
164
165 let wrapped = OperationWrapper::new(handler, self.state.clone());
166
167 let pair = ObjectOperationPair {
168 object_name,
169 operation_name,
170 };
171
172 self.operation_handlers.insert(pair, wrapped);
173
174 self.metadata.register_operation::<O, D>();
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 pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self {
184 self.metadata.register_object::<O>();
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: Arc<GiteratedStack>| {
192 async move {
193 for (_object_name, object_meta) in stack.metadata.objects.iter() {
194 if (object_meta.from_str)(&operation.0).is_ok() {
195 return Ok(ObjectResponse(operation.0));
196 }
197 }
198
199 Err(OperationError::Unhandled)
200 }
201 .boxed_local()
202 };
203
204 self.operation(handler);
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 pub fn setting<T: Setting + 'static>(&mut self) -> &mut Self {
214 self.metadata.register_setting::<T>();
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 pub fn value<O, V, A, F>(&mut self, handler: F) -> &mut Self
226 where
227 O: GiteratedObject + 'static,
228 V: GiteratedObjectValue<Object = O> + 'static + Clone,
229 F: GiteratedOperationHandler<A, O, GetValueTyped<V>, S> + Clone + 'static + Send + Sync,
230 {
231 let object_name = handler.object_name().to_string();
232 let value_name = V::value_name().to_string();
233
234 let wrapped = OperationWrapper::new(handler, self.state.clone());
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: GetValueTyped<AnyValue<O>>,
242 _state: S,
243 operation_state: StackOperationState,
244 stack: Arc<GiteratedStack>| {
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 (target, getter) 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 &(Box::new(object.clone()) as Box<dyn Any + Send + Sync>),
262 &(Box::new(GetValueTyped::<V> {
263 value_name: operation.value_name,
264 ty: Default::default(),
265 }) as Box<dyn Any + Send + Sync>),
266 &operation_state,
267 )
268 .await {
269 Ok(success) => Ok(*success.downcast::<<GetValueTyped<V> as GiteratedOperation<O>>::Success>().unwrap()),
270 Err(err) => Err(match err {
271 OperationError::Operation(failure) => OperationError::Operation(*failure.downcast::<<GetValueTyped<V> as GiteratedOperation<O>>::Failure>().unwrap()),
272 OperationError::Internal(internal) => OperationError::Internal(internal),
273 OperationError::Unhandled => OperationError::Unhandled,
274 }),
275 }
276 }
277
278 Err(OperationError::Unhandled)
279 }
280 .boxed_local()
281 };
282
283 assert!(self
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.register_value::<O, V>();
295
296 self
297 }
298
299 /// Register a handler for [`GetSetting`] for it's associated object type.
300 pub fn object_settings<O, A, F>(&mut self, handler: F) -> &mut Self
301 where
302 O: GiteratedObject + 'static,
303 F: GiteratedOperationHandler<A, O, GetSetting, S> + Clone + 'static + Send + Sync,
304 {
305 let object_name = handler.object_name().to_string();
306
307 let wrapped = OperationWrapper::new(handler, self.state.clone());
308
309 assert!(self.setting_getters.insert(object_name, wrapped).is_none());
310
311 self
312 }
313 }
314
315 impl RuntimeMetadata {
316 fn register_object<O: GiteratedObject + 'static>(&mut self) {
317 let object_name = O::object_name().to_string();
318
319 let object_meta = ObjectMeta::new::<O>();
320
321 if self.objects.insert(object_name, object_meta).is_some() {
322 trace!(
323 "Registration of object {} overwrote previous registration.",
324 O::object_name()
325 );
326 } else {
327 trace!("Registration of object {}.", O::object_name())
328 }
329 }
330
331 fn register_operation<O: GiteratedObject + 'static, D: GiteratedOperation<O> + 'static>(
332 &mut self,
333 ) {
334 let object_name = O::object_name().to_string();
335 let operation_name = D::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 OperationMeta::new::<O, D>(),
345 )
346 .is_some()
347 {
348 trace!(
349 "Registration of object operation {}<{}> overwrote previous registration.",
350 D::operation_name(),
351 O::object_name()
352 );
353 } else {
354 trace!(
355 "Registration of object operation {}<{}>.",
356 D::operation_name(),
357 O::object_name()
358 )
359 }
360 }
361
362 fn register_value<
363 O: GiteratedObject + 'static,
364 V: GiteratedObjectValue<Object = O> + 'static,
365 >(
366 &mut self,
367 ) {
368 let object_name = O::object_name().to_string();
369 let value_name = V::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 ValueMeta::new::<V>(),
379 )
380 .is_some()
381 {
382 trace!(
383 "Registration of value <{}>::{} overwrote previous registration.",
384 O::object_name(),
385 V::value_name()
386 );
387 } else {
388 trace!(
389 "Registration of value <{}>::{}.",
390 O::object_name(),
391 V::value_name()
392 );
393 }
394 }
395
396 fn register_setting<S: Setting + 'static>(&mut self) {
397 let setting_name = S::name().to_string();
398
399 if self
400 .settings
401 .insert(setting_name.clone(), SettingMeta::new::<S>())
402 .is_some()
403 {
404 trace!(
405 "Registration of setting {} overwrote previous registration.",
406 S::name()
407 );
408 } else {
409 trace!("Registration of setting {}.", S::name());
410 }
411 }
412
413 fn append(&mut self, other: Self) {
414 self.objects.extend(other.objects);
415 self.operations.extend(other.operations);
416 self.values.extend(other.values);
417 self.settings.extend(other.settings);
418 }
419 }
420 impl GiteratedStack {
421 /// Handles a giterated network message, returning either a raw success
422 /// payload or a serialized error payload.
423 pub async fn handle_network_message(
424 &self,
425 message: AuthenticatedPayload,
426 operation_state: &StackOperationState,
427 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
428 let message: GiteratedMessage<AnyObject, AnyOperation> = message.into_message();
429
430 // Deserialize the object, also getting the object type's name
431 let (object_type, object) = {
432 let mut result = None;
433
434 for (object_type, object_meta) in self.metadata.objects.iter() {
435 if let Ok(object) = (object_meta.from_str)(&message.object.0) {
436 result = Some((object_type.clone(), object));
437 break;
438 }
439 }
440
441 result
442 }
443 .ok_or_else(|| OperationError::Unhandled)?;
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 = serde_json::from_slice(&message.payload.0).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(|err| match err {
466 OperationError::Operation(operation) => OperationError::Operation(operation),
467 OperationError::Internal(internal) => {
468 OperationError::Internal(internal.context(format!(
469 "{}::get_value::<{}> outcome",
470 object_type, operation.value_name
471 )))
472 }
473 OperationError::Unhandled => OperationError::Unhandled,
474 });
475
476 return result;
477 } else if message.operation == "get_setting" {
478 let operation: GetSetting = serde_json::from_slice(&message.payload.0).unwrap();
479 let setting_meta = self
480 .metadata
481 .settings
482 .get(&operation.setting_name)
483 .ok_or_else(|| OperationError::Unhandled)?;
484 let raw_result = self
485 .get_setting(object, object_type.clone(), operation, operation_state)
486 .await;
487 return match raw_result {
488 Ok(success) => {
489 // Success is the setting type, serialize it
490 let serialized = (setting_meta.serialize)(success).unwrap();
491
492 Ok(serde_json::to_vec(&serialized).unwrap())
493 }
494 Err(err) => Err(match err {
495 OperationError::Operation(failure) => {
496 // We know how to resolve this type
497 let failure: GetSettingError = *failure.downcast().unwrap();
498
499 OperationError::Operation(serde_json::to_vec(&failure).unwrap())
500 }
501 OperationError::Internal(internal) => {
502 OperationError::Internal(internal.context(format!(
503 "{}::get_setting::<{}> handler outcome",
504 object_type, setting_meta.name
505 )))
506 }
507 OperationError::Unhandled => OperationError::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(&target)
521 .ok_or_else(|| OperationError::Unhandled)?;
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(&target)
534 .ok_or_else(|| OperationError::Unhandled)?;
535
536 let operation =
537 (meta.deserialize)(&message.payload.0).as_internal_error_with_context(format!(
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(&object, &operation, operation_state).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(success) => Ok((meta.serialize_success)(success).as_internal_error()?),
566 Err(err) => Err(match err {
567 OperationError::Operation(failure) => {
568 OperationError::Operation((meta.serialize_error)(failure).as_internal_error()?)
569 }
570 OperationError::Internal(internal) => {
571 OperationError::Internal(internal.context(format!(
572 "operation {}::{} handler outcome",
573 target.object_name, target.operation_name
574 )))
575 }
576 OperationError::Unhandled => OperationError::Unhandled,
577 }),
578 }
579 }
580
581 pub async fn network_get_value(
582 &self,
583 object: Box<dyn Any + Send + Sync>,
584 object_kind: String,
585 operation: GetValue,
586 operation_state: &StackOperationState,
587 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
588 trace!("Handling network get_value for {}", operation.value_name);
589
590 let value_meta = self
591 .metadata
592 .values
593 .get(&ObjectValuePair {
594 object_kind: object_kind.clone(),
595 value_kind: operation.value_name.clone(),
596 })
597 .ok_or_else(|| OperationError::Unhandled)?;
598
599 for (target, getter) 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(&(object), &((value_meta.typed_get)()), &operation_state)
610 .await
611 {
612 Ok(success) => {
613 // Serialize success, which is the value type itself
614 let serialized = (value_meta.serialize)(success).as_internal_error()?;
615
616 Ok(serialized)
617 }
618 Err(err) => Err(match err {
619 OperationError::Operation(failure) => {
620 // Failure is sourced from GetValue operation, but this is hardcoded for now
621 let failure: GetValueError = *failure.downcast().unwrap();
622
623 OperationError::Operation(serde_json::to_vec(&failure).as_internal_error()?)
624 }
625 OperationError::Internal(internal) => OperationError::Internal(internal),
626 OperationError::Unhandled => OperationError::Unhandled,
627 }),
628 };
629 }
630
631 Err(OperationError::Unhandled)
632 }
633
634 pub async fn get_setting(
635 &self,
636 object: Box<dyn Any + Send + Sync>,
637 object_kind: String,
638 operation: GetSetting,
639 operation_state: &StackOperationState,
640 ) -> Result<Box<dyn Any + Send + Sync>, OperationError<Box<dyn Any + Send + Sync>>> {
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(&object_kind)
650 .ok_or_else(|| OperationError::Unhandled)?;
651
652 setting_getter
653 .handle(&object, &(Box::new(operation) as Box<_>), operation_state)
654 .await
655 }
656
657 pub async fn network_set_setting(
658 &self,
659 _operation: SetSetting,
660 _operation_state: &StackOperationState,
661 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
662 todo!()
663 }
664 }
665
666 use core::fmt::Debug;
667
668 #[async_trait::async_trait(?Send)]
669 impl ObjectBackend<StackOperationState> for Arc<GiteratedStack> {
670 async fn object_operation<O, D>(
671 &self,
672 in_object: O,
673 operation_name: &str,
674 payload: D,
675 operation_state: &StackOperationState,
676 ) -> Result<D::Success, OperationError<D::Failure>>
677 where
678 O: GiteratedObject + Debug + 'static,
679 D: GiteratedOperation<O> + Debug + 'static,
680 {
681 // Erase object and operation types.
682 let object = Box::new(in_object.clone()) as Box<dyn Any + Send + Sync>;
683 let operation = Box::new(payload) as Box<dyn Any + Send + Sync>;
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 (_, meta) in self.metadata.values.iter() {
689 if (meta.is_get_value_typed)(&operation) {
690 value_meta = Some(meta);
691 break;
692 }
693 }
694
695 let value_meta = value_meta.ok_or_else(|| OperationError::Unhandled)?;
696
697 let value_name = value_meta.name.clone();
698
699 trace!(
700 "Handling get_value for {}::{}",
701 O::object_name(),
702 value_name
703 );
704
705 for (target, getter) in self.value_getters.iter() {
706 if target.object_kind != O::object_name() {
707 continue;
708 }
709
710 if target.value_kind != value_name {
711 continue;
712 }
713
714 return match getter
715 .handle(&(object), &((value_meta.typed_get)()), &operation_state)
716 .await
717 {
718 Ok(success) => Ok(*success.downcast().unwrap()),
719 Err(err) => Err(match err {
720 OperationError::Operation(failure) => {
721 OperationError::Operation(*failure.downcast::<D::Failure>().unwrap())
722 }
723 OperationError::Internal(internal) => {
724 OperationError::Internal(internal.context(format!(
725 "{}::get_value::<{}> handler outcome",
726 O::object_name(),
727 value_name
728 )))
729 }
730 OperationError::Unhandled => OperationError::Unhandled,
731 }),
732 };
733 }
734
735 return Err(OperationError::Unhandled);
736 } else if operation.is::<GetSetting>() {
737 let get_setting: Box<GetSetting> = operation.downcast().unwrap();
738 let setting_name = get_setting.setting_name.clone();
739
740 let raw_result = self
741 .get_setting(
742 object,
743 O::object_name().to_string(),
744 *get_setting,
745 operation_state,
746 )
747 .await;
748
749 return match raw_result {
750 Ok(success) => {
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(*success.downcast().unwrap())
756 }
757 Err(err) => Err(match err {
758 OperationError::Operation(failure) => {
759 // We know this is the right type
760 OperationError::Operation(*failure.downcast().unwrap())
761 }
762 OperationError::Internal(internal) => {
763 OperationError::Internal(internal.context(format!(
764 "{}::get_setting::<{}> handler outcome",
765 O::object_name(),
766 setting_name
767 )))
768 }
769 OperationError::Unhandled => OperationError::Unhandled,
770 }),
771 };
772 } else if operation.is::<SetSetting>() {
773 todo!()
774 } else if operation.is::<ObjectRequest>() {
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 (target, operation_meta) in self.metadata.operations.iter() {
783 // Skip elements that we know will not match
784 if target.object_name != O::object_name() {
785 continue;
786 }
787
788 if target.operation_name != operation_name {
789 continue;
790 }
791
792 if (operation_meta.any_is_same)(&operation) {
793 operation_type = Some(target.clone());
794 break;
795 }
796 }
797
798 operation_type
799 }
800 .ok_or_else(|| OperationError::Unhandled)?;
801
802 // Resolve the handler from our handler tree
803 let handler_tree = self
804 .operation_handlers
805 .get(&operation_type)
806 .ok_or_else(|| OperationError::Unhandled)?;
807
808 let raw_result = handler_tree
809 .handle(&object, &operation, operation_state)
810 .await;
811
812 // Convert the dynamic result back into its concrete type
813 match raw_result {
814 Ok(result) => Ok(*result.downcast::<D::Success>().unwrap()),
815 Err(err) => Err(match err {
816 OperationError::Internal(internal) => {
817 OperationError::Internal(internal.context(format!(
818 "operation {}::{} handler outcome",
819 operation_type.object_name, operation_type.operation_name
820 )))
821 }
822 OperationError::Operation(boxed_error) => {
823 OperationError::Operation(*boxed_error.downcast::<D::Failure>().unwrap())
824 }
825 OperationError::Unhandled => OperationError::Unhandled,
826 }),
827 }
828 }
829
830 async fn get_object<O: GiteratedObject + Debug + 'static>(
831 &self,
832 object_str: &str,
833 _operation_state: &StackOperationState,
834 ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> {
835 // TODO: Authorization?
836 for (_object_name, object_meta) in self.metadata.objects.iter() {
837 if let Ok(object) = (object_meta.from_str)(object_str) {
838 return Ok(unsafe {
839 Object::new_unchecked(*object.downcast::<O>().unwrap(), self.clone())
840 });
841 }
842 }
843
844 Err(OperationError::Unhandled)
845 }
846 }
847