reactive_graph_runtime_impl/
runtime_getter.rs

1use std::any::Any;
2use std::future::Future;
3use std::sync::Arc;
4use std::time::Duration;
5
6use log::error;
7use springtime_di::instance_provider::CastFunction;
8use springtime_di::instance_provider::ComponentInstanceAnyPtr;
9use springtime_di::instance_provider::ComponentInstanceProvider;
10use springtime_di::instance_provider::ComponentInstanceProviderError;
11use springtime_di::instance_provider::TypedComponentInstanceProvider;
12
13use reactive_graph_di::get_shared_component_factory;
14use reactive_graph_runtime_api::Runtime;
15
16use crate::RuntimeImpl;
17
18pub fn get_runtime() -> Arc<dyn Runtime + Send + Sync> {
19    let mut component_factory = get_shared_component_factory();
20    match TypedComponentInstanceProvider::primary_instance_typed::<RuntimeImpl>(&mut component_factory) {
21        Ok(runtime) => runtime,
22        Err(ComponentInstanceProviderError::NoPrimaryInstance { type_id, type_name }) => {
23            error!("Missing component {type_name:?}");
24            let instances: Result<Vec<(ComponentInstanceAnyPtr, CastFunction)>, ComponentInstanceProviderError> = component_factory.instances(type_id);
25            match instances {
26                Ok(instances) => {
27                    for (component_instance, _) in instances {
28                        error!("Type Id: {:?}", component_instance.type_id());
29                    }
30                }
31                Err(e) => {
32                    error!("{e:?}");
33                }
34            }
35            panic!("Cannot find a primary instance for component '{type_id:?}/{type_name:?}' - either none or multiple exists without a primary marker.");
36        }
37        Err(ComponentInstanceProviderError::IncompatibleComponent { type_id, type_name }) => {
38            panic!("Tried to downcast component to incompatible type: {type_id:?}/{type_name}");
39        }
40        Err(ComponentInstanceProviderError::NoNamedInstance(type_name)) => {
41            panic!("Cannot find named component: {type_name}");
42        }
43        Err(ComponentInstanceProviderError::UnrecognizedScope(scope)) => {
44            panic!("Unrecognized scope: {scope}");
45        }
46        Err(ComponentInstanceProviderError::DependencyCycle { type_id, type_name }) => {
47            panic!("Detected dependency cycle for: {type_id:?}/{type_name:?}");
48        }
49        Err(ComponentInstanceProviderError::ConstructorError(constructor_error)) => {
50            panic!("Error in component constructor: {constructor_error}");
51        }
52    }
53}
54
55pub async fn main<F1, F2, C1, C2>(pre_config: C1, post_config: C2)
56where
57    F1: Future<Output = ()>,
58    F2: Future<Output = ()>,
59    C1: FnOnce(Arc<dyn Runtime>) -> F1,
60    C2: FnOnce(Arc<dyn Runtime>) -> F2,
61{
62    {
63        let runtime = get_runtime();
64        // Runtime Configuration Phase
65        pre_config(runtime.clone()).await;
66        runtime.config().await;
67        post_config(runtime.clone()).await;
68        // Runtime Lifecycle
69        runtime.init().await;
70        runtime.post_init().await;
71        runtime.run().await;
72        runtime.pre_shutdown().await;
73        runtime.shutdown().await;
74    } // Destruct the whole runtime
75    tokio::time::sleep(Duration::from_millis(2000)).await;
76}