reactive_graph_runtime_impl/
runtime_impl.rs

1use std::sync::Arc;
2use std::sync::atomic::AtomicBool;
3use std::sync::atomic::Ordering;
4use std::time::Duration;
5
6use async_trait::async_trait;
7use log::debug;
8use log::info;
9use springtime_di::Component;
10use springtime_di::component_alias;
11use tokio::time::error::Elapsed;
12
13use reactive_graph_behaviour_service_api::BehaviourSystem;
14use reactive_graph_behaviour_service_api::EntityBehaviourManager;
15use reactive_graph_behaviour_service_api::EntityBehaviourRegistry;
16use reactive_graph_behaviour_service_api::EntityComponentBehaviourManager;
17use reactive_graph_behaviour_service_api::EntityComponentBehaviourRegistry;
18use reactive_graph_behaviour_service_api::RelationBehaviourManager;
19use reactive_graph_behaviour_service_api::RelationBehaviourRegistry;
20use reactive_graph_behaviour_service_api::RelationComponentBehaviourManager;
21use reactive_graph_behaviour_service_api::RelationComponentBehaviourRegistry;
22use reactive_graph_command_api::CommandManager;
23use reactive_graph_command_api::CommandSystem;
24use reactive_graph_command_api::CommandTypeProvider;
25use reactive_graph_command_impl::CommandSystemImpl;
26use reactive_graph_config_api::ConfigManager;
27use reactive_graph_config_api::ConfigSystem;
28use reactive_graph_config_impl::ConfigSystemImpl;
29use reactive_graph_dynamic_graph_api::DynamicGraphQueryService;
30use reactive_graph_dynamic_graph_api::DynamicGraphSchemaManager;
31use reactive_graph_dynamic_graph_api::DynamicGraphSystem;
32use reactive_graph_graphql_api::GraphQLQueryService;
33use reactive_graph_graphql_api::GraphQLSchemaManager;
34use reactive_graph_graphql_api::GraphQLSystem;
35use reactive_graph_instance_system_api::EntityInstanceImportExportManager;
36use reactive_graph_instance_system_api::InstanceSystem;
37use reactive_graph_instance_system_api::RelationInstanceImportExportManager;
38use reactive_graph_lifecycle::Lifecycle;
39use reactive_graph_plugin_graphql_api::PluginGraphQLSystem;
40use reactive_graph_plugin_graphql_api::PluginQueryService;
41use reactive_graph_plugin_graphql_api::PluginSchemaManager;
42use reactive_graph_plugin_service_api::PluginContainerManager;
43use reactive_graph_plugin_service_api::PluginContextFactory;
44use reactive_graph_plugin_service_api::PluginRepositoryManager;
45use reactive_graph_plugin_service_api::PluginResolver;
46use reactive_graph_plugin_service_api::PluginSystem;
47use reactive_graph_reactive_service_api::ReactiveEntityManager;
48use reactive_graph_reactive_service_api::ReactiveFlowManager;
49use reactive_graph_reactive_service_api::ReactiveInstanceEventManager;
50use reactive_graph_reactive_service_api::ReactiveRelationManager;
51use reactive_graph_reactive_service_api::ReactiveSystem;
52use reactive_graph_remotes_api::InstanceService;
53use reactive_graph_remotes_api::RemotesManager;
54use reactive_graph_remotes_api::RemotesSystem;
55use reactive_graph_remotes_impl::RemotesSystemImpl;
56use reactive_graph_remotes_model::InstanceAddress;
57use reactive_graph_runtime_api::Runtime;
58use reactive_graph_runtime_graphql_api::RuntimeGraphQLSystem;
59use reactive_graph_runtime_graphql_api::RuntimeQueryService;
60use reactive_graph_runtime_graphql_api::RuntimeSchemaManager;
61use reactive_graph_runtime_service_api::RuntimeSystem;
62use reactive_graph_runtime_service_api::ShutdownManager;
63use reactive_graph_runtime_web_api::GraphQLServer;
64use reactive_graph_runtime_web_api::WebResourceManager;
65use reactive_graph_runtime_web_api::WebSystem;
66use reactive_graph_type_system_api::ComponentImportExportManager;
67use reactive_graph_type_system_api::ComponentManager;
68use reactive_graph_type_system_api::ComponentProviderRegistry;
69use reactive_graph_type_system_api::EntityTypeImportExportManager;
70use reactive_graph_type_system_api::EntityTypeManager;
71use reactive_graph_type_system_api::EntityTypeProviderRegistry;
72use reactive_graph_type_system_api::FlowTypeImportExportManager;
73use reactive_graph_type_system_api::FlowTypeManager;
74use reactive_graph_type_system_api::FlowTypeProviderRegistry;
75use reactive_graph_type_system_api::NamespaceManager;
76use reactive_graph_type_system_api::RelationTypeImportExportManager;
77use reactive_graph_type_system_api::RelationTypeManager;
78use reactive_graph_type_system_api::RelationTypeProviderRegistry;
79use reactive_graph_type_system_api::TypeSystem;
80use reactive_graph_type_system_api::TypeSystemEventManager;
81
82pub struct RunningState(Arc<AtomicBool>);
83
84fn create_running_state() -> RunningState {
85    RunningState(Arc::new(AtomicBool::new(false)))
86}
87
88#[derive(Component)]
89pub struct RuntimeImpl {
90    #[component(default = "create_running_state")]
91    running: RunningState,
92    type_system: Arc<dyn TypeSystem + Send + Sync>,
93    reactive_system: Arc<dyn ReactiveSystem + Send + Sync>,
94    behaviour_system: Arc<dyn BehaviourSystem + Send + Sync>,
95    instance_system: Arc<dyn InstanceSystem + Send + Sync>,
96    command_system: Arc<CommandSystemImpl>,
97    runtime_system: Arc<dyn RuntimeSystem + Send + Sync>,
98    remotes_system: Arc<RemotesSystemImpl>,
99    config_system: Arc<ConfigSystemImpl>,
100    graphql_system: Arc<dyn GraphQLSystem + Send + Sync>,
101    dynamic_graph_system: Arc<dyn DynamicGraphSystem + Send + Sync>,
102    runtime_graphql_system: Arc<dyn RuntimeGraphQLSystem + Send + Sync>,
103    plugin_graphql_system: Arc<dyn PluginGraphQLSystem + Send + Sync>,
104    plugin_system: Arc<dyn PluginSystem + Send + Sync>,
105    web_system: Arc<dyn WebSystem + Send + Sync>,
106}
107
108impl RuntimeImpl {
109    async fn wait_for_started_internal(&self) {
110        // TODO: Add upper bound timeout (for example 30 sec)
111        while !self.is_running() {
112            tokio::time::sleep(Duration::from_millis(100)).await;
113        }
114    }
115}
116
117#[async_trait]
118#[component_alias]
119impl Runtime for RuntimeImpl {
120    async fn config(&self) {
121        self.config_system.init().await;
122    }
123
124    async fn run(&self) {
125        // Signal handling
126        let terminate = Arc::new(AtomicBool::new(false));
127        // This channel allows the main thread to stop the GraphQL server thread
128        let (graphql_server_stop_sender, graphql_server_stop_receiver) = crossbeam::channel::unbounded::<()>();
129        // This channel allows the GraphQL server thread to tell the main thread that it has been finished
130        let (graphql_server_stopped_sender, graphql_server_stopped_receiver) = crossbeam::channel::unbounded::<()>();
131        // Clone GraphQL server and move the reference into the GraphQL server thread
132        let graphql_server = self.web_system.get_graphql_server();
133        // GraphQL server thread: Create a new thread for the GraphQL server
134        // TODO: Use tokio task Builder to name the task
135        // tokio::task::Builder::new().name("rg_server").spawn()
136        let graphql_server_handle = tokio::spawn(async move {
137            // Run the GraphQL server
138            info!("Run the GraphQL server.");
139            graphql_server.serve(graphql_server_stop_receiver).await;
140            debug!("Successfully stopped GraphQL Server.");
141            // Tell the main thread, that the GraphQL server thread has finished
142            let _result = graphql_server_stopped_sender.send(());
143        });
144
145        {
146            self.running.0.store(true, Ordering::Relaxed);
147        }
148
149        {
150            let _r_sigint = signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&terminate));
151            let _r_sigterm = signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&terminate));
152
153            let mut stopping = false;
154            while self.is_running() && !stopping && !terminate.load(Ordering::Relaxed) {
155                tokio::time::sleep(Duration::from_millis(100)).await;
156                let r = graphql_server_stopped_receiver.try_recv();
157                if r.is_ok() {
158                    debug!("Stopping the main thread");
159                    stopping = true;
160                }
161                if self.runtime_system.get_shutdown_manager().is_shutdown() {
162                    stopping = true;
163                }
164            }
165        } // Drop "running"
166
167        // Stop GraphQL server thread, if it is still running
168        debug!("Stopping the GraphQL server thread");
169        let _graphql_server_stop_result = graphql_server_stop_sender.send_timeout((), Duration::from_millis(100));
170
171        // Be sure that the GraphQL server thread is gone
172        let _ = graphql_server_handle.await;
173        info!("Bye.");
174
175        // Ensure the running state is now set to false even if the loop was terminated
176        // externally because the running state is checked from outside.
177        {
178            self.running.0.store(false, Ordering::Relaxed);
179        }
180    }
181
182    fn stop(&self) {
183        {
184            self.running.0.store(false, Ordering::Relaxed);
185        }
186    }
187
188    fn is_running(&self) -> bool {
189        self.running.0.load(Ordering::Relaxed)
190        // *self.running.0.read().unwrap().deref()
191    }
192
193    async fn wait_for_started(&self, timeout_duration: Duration) -> Result<(), Elapsed> {
194        tokio::time::timeout(timeout_duration, self.wait_for_started_internal()).await
195    }
196
197    async fn wait_for_stopped(&self) {
198        while self.is_running() {
199            tokio::time::sleep(Duration::from_millis(100)).await;
200        }
201    }
202
203    async fn wait_for_stopped_with_timeout(&self, timeout_duration: Duration) -> Result<(), Elapsed> {
204        tokio::time::timeout(timeout_duration, self.wait_for_stopped()).await
205    }
206
207    fn address(&self) -> InstanceAddress {
208        self.remotes_system.get_instance_service().get_instance_info().address()
209    }
210}
211
212impl TypeSystem for RuntimeImpl {
213    fn get_component_manager(&self) -> Arc<dyn ComponentManager + Send + Sync> {
214        self.type_system.get_component_manager()
215    }
216
217    fn get_component_import_export_manager(&self) -> Arc<dyn ComponentImportExportManager + Send + Sync> {
218        self.type_system.get_component_import_export_manager()
219    }
220
221    fn get_component_provider_registry(&self) -> Arc<dyn ComponentProviderRegistry + Send + Sync> {
222        self.type_system.get_component_provider_registry()
223    }
224
225    fn get_entity_type_manager(&self) -> Arc<dyn EntityTypeManager + Send + Sync> {
226        self.type_system.get_entity_type_manager()
227    }
228
229    fn get_entity_type_import_export_manager(&self) -> Arc<dyn EntityTypeImportExportManager + Send + Sync> {
230        self.type_system.get_entity_type_import_export_manager()
231    }
232
233    fn get_entity_type_provider_registry(&self) -> Arc<dyn EntityTypeProviderRegistry + Send + Sync> {
234        self.type_system.get_entity_type_provider_registry()
235    }
236
237    fn get_flow_type_manager(&self) -> Arc<dyn FlowTypeManager + Send + Sync> {
238        self.type_system.get_flow_type_manager()
239    }
240
241    fn get_flow_type_import_export_manager(&self) -> Arc<dyn FlowTypeImportExportManager + Send + Sync> {
242        self.type_system.get_flow_type_import_export_manager()
243    }
244
245    fn get_flow_type_provider_registry(&self) -> Arc<dyn FlowTypeProviderRegistry + Send + Sync> {
246        self.type_system.get_flow_type_provider_registry()
247    }
248
249    fn get_namespace_manager(&self) -> Arc<dyn NamespaceManager + Send + Sync> {
250        self.type_system.get_namespace_manager()
251    }
252
253    fn get_relation_type_manager(&self) -> Arc<dyn RelationTypeManager + Send + Sync> {
254        self.type_system.get_relation_type_manager()
255    }
256
257    fn get_relation_type_import_export_manager(&self) -> Arc<dyn RelationTypeImportExportManager + Send + Sync> {
258        self.type_system.get_relation_type_import_export_manager()
259    }
260
261    fn get_relation_type_provider_registry(&self) -> Arc<dyn RelationTypeProviderRegistry + Send + Sync> {
262        self.type_system.get_relation_type_provider_registry()
263    }
264
265    fn get_type_system_event_manager(&self) -> Arc<dyn TypeSystemEventManager + Send + Sync> {
266        self.type_system.get_type_system_event_manager()
267    }
268}
269
270impl ReactiveSystem for RuntimeImpl {
271    fn get_reactive_entity_manager(&self) -> Arc<dyn ReactiveEntityManager + Send + Sync> {
272        self.reactive_system.get_reactive_entity_manager()
273    }
274
275    fn get_reactive_flow_manager(&self) -> Arc<dyn ReactiveFlowManager + Send + Sync> {
276        self.reactive_system.get_reactive_flow_manager()
277    }
278
279    fn get_reactive_relation_manager(&self) -> Arc<dyn ReactiveRelationManager + Send + Sync> {
280        self.reactive_system.get_reactive_relation_manager()
281    }
282
283    fn get_reactive_instance_event_manager(&self) -> Arc<dyn ReactiveInstanceEventManager + Send + Sync> {
284        self.reactive_system.get_reactive_instance_event_manager()
285    }
286
287    fn type_system(&self) -> Arc<dyn TypeSystem + Send + Sync> {
288        self.reactive_system.type_system()
289    }
290
291    fn behaviour_system(&self) -> Arc<dyn BehaviourSystem + Send + Sync> {
292        self.reactive_system.behaviour_system()
293    }
294}
295
296impl BehaviourSystem for RuntimeImpl {
297    fn get_entity_behaviour_manager(&self) -> Arc<dyn EntityBehaviourManager + Send + Sync> {
298        self.behaviour_system.get_entity_behaviour_manager()
299    }
300
301    fn get_entity_behaviour_registry(&self) -> Arc<dyn EntityBehaviourRegistry + Send + Sync> {
302        self.behaviour_system.get_entity_behaviour_registry()
303    }
304
305    fn get_entity_component_behaviour_manager(&self) -> Arc<dyn EntityComponentBehaviourManager + Send + Sync> {
306        self.behaviour_system.get_entity_component_behaviour_manager()
307    }
308
309    fn get_entity_component_behaviour_registry(&self) -> Arc<dyn EntityComponentBehaviourRegistry + Send + Sync> {
310        self.behaviour_system.get_entity_component_behaviour_registry()
311    }
312
313    fn get_relation_behaviour_manager(&self) -> Arc<dyn RelationBehaviourManager + Send + Sync> {
314        self.behaviour_system.get_relation_behaviour_manager()
315    }
316
317    fn get_relation_behaviour_registry(&self) -> Arc<dyn RelationBehaviourRegistry + Send + Sync> {
318        self.behaviour_system.get_relation_behaviour_registry()
319    }
320
321    fn get_relation_component_behaviour_manager(&self) -> Arc<dyn RelationComponentBehaviourManager + Send + Sync> {
322        self.behaviour_system.get_relation_component_behaviour_manager()
323    }
324
325    fn get_relation_component_behaviour_registry(&self) -> Arc<dyn RelationComponentBehaviourRegistry + Send + Sync> {
326        self.behaviour_system.get_relation_component_behaviour_registry()
327    }
328
329    fn type_system(&self) -> Arc<dyn TypeSystem + Send + Sync> {
330        self.behaviour_system.type_system()
331    }
332}
333
334impl InstanceSystem for RuntimeImpl {
335    fn get_entity_instance_import_export_manager(&self) -> Arc<dyn EntityInstanceImportExportManager + Send + Sync> {
336        self.instance_system.get_entity_instance_import_export_manager()
337    }
338
339    fn get_relation_instance_import_export_manager(&self) -> Arc<dyn RelationInstanceImportExportManager + Send + Sync> {
340        self.instance_system.get_relation_instance_import_export_manager()
341    }
342
343    fn reactive_system(&self) -> Arc<dyn ReactiveSystem + Send + Sync> {
344        self.reactive_system.clone()
345    }
346}
347
348impl CommandSystem for RuntimeImpl {
349    fn get_command_manager(&self) -> Arc<dyn CommandManager + Send + Sync> {
350        self.command_system.get_command_manager()
351    }
352
353    fn get_command_type_provider(&self) -> Arc<dyn CommandTypeProvider + Send + Sync> {
354        self.command_system.get_command_type_provider()
355    }
356
357    fn type_system(&self) -> Arc<dyn TypeSystem + Send + Sync> {
358        self.command_system.type_system()
359    }
360
361    fn reactive_system(&self) -> Arc<dyn ReactiveSystem + Send + Sync> {
362        self.command_system.reactive_system()
363    }
364}
365
366impl ConfigSystem for RuntimeImpl {
367    fn get_config_manager(&self) -> Arc<dyn ConfigManager + Send + Sync> {
368        self.config_system.get_config_manager()
369    }
370}
371
372impl RemotesSystem for RuntimeImpl {
373    fn get_instance_service(&self) -> Arc<dyn InstanceService + Send + Sync> {
374        self.remotes_system.get_instance_service()
375    }
376
377    fn get_remotes_manager(&self) -> Arc<dyn RemotesManager + Send + Sync> {
378        self.remotes_system.get_remotes_manager()
379    }
380
381    fn config_system(&self) -> Arc<dyn ConfigSystem + Send + Sync> {
382        self.remotes_system.config_system()
383    }
384}
385
386impl RuntimeSystem for RuntimeImpl {
387    fn get_shutdown_manager(&self) -> Arc<dyn ShutdownManager + Send + Sync> {
388        self.runtime_system.get_shutdown_manager()
389    }
390}
391
392impl WebSystem for RuntimeImpl {
393    fn get_graphql_server(&self) -> Arc<dyn GraphQLServer + Send + Sync> {
394        self.web_system.get_graphql_server()
395    }
396
397    fn get_web_resource_manager(&self) -> Arc<dyn WebResourceManager + Send + Sync> {
398        self.web_system.get_web_resource_manager()
399    }
400
401    fn type_system(&self) -> Arc<dyn TypeSystem + Send + Sync> {
402        self.web_system.type_system()
403    }
404
405    fn reactive_system(&self) -> Arc<dyn ReactiveSystem + Send + Sync> {
406        self.web_system.reactive_system()
407    }
408
409    fn config_system(&self) -> Arc<dyn ConfigSystem + Send + Sync> {
410        self.web_system.config_system()
411    }
412
413    fn runtime_graphql_system(&self) -> Arc<dyn RuntimeGraphQLSystem + Send + Sync> {
414        self.web_system.runtime_graphql_system()
415    }
416
417    fn plugin_graphql_system(&self) -> Arc<dyn PluginGraphQLSystem + Send + Sync> {
418        self.web_system.plugin_graphql_system()
419    }
420
421    fn dynamic_graph_system(&self) -> Arc<dyn DynamicGraphSystem + Send + Sync> {
422        self.web_system.dynamic_graph_system()
423    }
424
425    fn graphql_system(&self) -> Arc<dyn GraphQLSystem + Send + Sync> {
426        self.web_system.graphql_system()
427    }
428}
429
430impl GraphQLSystem for RuntimeImpl {
431    fn get_graphql_query_service(&self) -> Arc<dyn GraphQLQueryService + Send + Sync> {
432        self.graphql_system.get_graphql_query_service()
433    }
434
435    fn get_graphql_schema_manager(&self) -> Arc<dyn GraphQLSchemaManager + Send + Sync> {
436        self.graphql_system.get_graphql_schema_manager()
437    }
438}
439
440impl DynamicGraphSystem for RuntimeImpl {
441    fn get_dynamic_graph_query_service(&self) -> Arc<dyn DynamicGraphQueryService + Send + Sync> {
442        self.dynamic_graph_system.get_dynamic_graph_query_service()
443    }
444
445    fn get_dynamic_graph_schema_manager(&self) -> Arc<dyn DynamicGraphSchemaManager + Send + Sync> {
446        self.dynamic_graph_system.get_dynamic_graph_schema_manager()
447    }
448
449    fn type_system(&self) -> Arc<dyn TypeSystem + Send + Sync> {
450        self.dynamic_graph_system.type_system()
451    }
452
453    fn reactive_system(&self) -> Arc<dyn ReactiveSystem + Send + Sync> {
454        self.dynamic_graph_system.reactive_system()
455    }
456}
457
458impl RuntimeGraphQLSystem for RuntimeImpl {
459    fn get_runtime_query_service(&self) -> Arc<dyn RuntimeQueryService + Send + Sync> {
460        self.runtime_graphql_system.get_runtime_query_service()
461    }
462
463    fn get_runtime_schema_manager(&self) -> Arc<dyn RuntimeSchemaManager + Send + Sync> {
464        self.runtime_graphql_system.get_runtime_schema_manager()
465    }
466}
467
468impl PluginGraphQLSystem for RuntimeImpl {
469    fn get_plugin_query_service(&self) -> Arc<dyn PluginQueryService + Send + Sync> {
470        self.plugin_graphql_system.get_plugin_query_service()
471    }
472
473    fn get_plugin_schema_manager(&self) -> Arc<dyn PluginSchemaManager + Send + Sync> {
474        self.plugin_graphql_system.get_plugin_schema_manager()
475    }
476}
477
478impl PluginSystem for RuntimeImpl {
479    fn get_plugin_context_factory(&self) -> Arc<dyn PluginContextFactory + Send + Sync> {
480        self.plugin_system.get_plugin_context_factory()
481    }
482
483    fn get_plugin_container_manager(&self) -> Arc<dyn PluginContainerManager + Send + Sync> {
484        self.plugin_system.get_plugin_container_manager()
485    }
486
487    fn get_plugin_repository_manager(&self) -> Arc<dyn PluginRepositoryManager + Send + Sync> {
488        self.plugin_system.get_plugin_repository_manager()
489    }
490
491    fn get_plugin_resolver(&self) -> Arc<dyn PluginResolver + Send + Sync> {
492        self.plugin_system.get_plugin_resolver()
493    }
494}
495
496#[async_trait]
497impl Lifecycle for RuntimeImpl {
498    async fn init(&self) {
499        // Order matters
500        self.type_system.init().await;
501        self.reactive_system.init().await;
502        self.behaviour_system.init().await;
503        self.instance_system.init().await;
504        //
505        self.command_system.init().await;
506        self.runtime_system.init().await;
507        // self.shutdown_manager.init().await;
508        self.remotes_system.init().await;
509        //
510        self.graphql_system.init().await;
511        self.dynamic_graph_system.init().await;
512        //
513        self.web_system.init().await;
514        // self.web_resource_manager.init().await;
515        // self.graphql_server.init().await;
516        //
517        self.plugin_system.init().await;
518    }
519
520    async fn post_init(&self) {
521        // Order matters
522        self.type_system.post_init().await;
523        self.reactive_system.post_init().await;
524        self.behaviour_system.post_init().await;
525        self.instance_system.post_init().await;
526        //
527        self.command_system.post_init().await;
528        // self.shutdown_manager.post_init().await;
529        self.runtime_system.post_init().await;
530        self.remotes_system.post_init().await;
531        //
532        self.graphql_system.post_init().await;
533        self.dynamic_graph_system.post_init().await;
534        //
535        self.web_system.post_init().await;
536        // self.web_resource_manager.post_init().await;
537        // self.graphql_server.post_init().await;
538        //
539        self.plugin_system.post_init().await;
540    }
541
542    async fn pre_shutdown(&self) {
543        // Reverse order matters
544        self.plugin_system.pre_shutdown().await;
545        //
546        // self.graphql_server.pre_shutdown().await;
547        // self.web_resource_manager.pre_shutdown().await;
548        self.web_system.pre_shutdown().await;
549        //
550        self.dynamic_graph_system.pre_shutdown().await;
551        self.graphql_system.pre_shutdown().await;
552        //
553        self.remotes_system.pre_shutdown().await;
554        // self.shutdown_manager.pre_shutdown().await;
555        self.runtime_system.pre_shutdown().await;
556        self.command_system.init().await;
557        //
558        self.instance_system.pre_shutdown().await;
559        self.behaviour_system.pre_shutdown().await;
560        self.reactive_system.pre_shutdown().await;
561        self.type_system.pre_shutdown().await;
562    }
563
564    async fn shutdown(&self) {
565        // Reverse order matters
566        self.plugin_system.shutdown().await;
567        //
568        // self.graphql_server.shutdown().await;
569        // self.web_resource_manager.shutdown().await;
570        self.web_system.shutdown().await;
571        //
572        self.dynamic_graph_system.shutdown().await;
573        self.graphql_system.shutdown().await;
574        //
575        self.remotes_system.shutdown().await;
576        // self.shutdown_manager.shutdown().await;
577        self.runtime_system.shutdown().await;
578        self.command_system.init().await;
579        //
580        self.instance_system.shutdown().await;
581        self.behaviour_system.shutdown().await;
582        self.reactive_system.shutdown().await;
583        self.type_system.shutdown().await;
584    }
585}
586
587#[cfg(test)]
588mod tests {
589    use std::time::Duration;
590
591    use log::LevelFilter;
592    use log4rs::Config;
593    use log4rs::append::console::ConsoleAppender;
594    use log4rs::config::Appender;
595    use log4rs::config::Root;
596
597    use crate::get_runtime;
598
599    /// This starts the runtime in an async environment.
600    ///
601    /// The runtime will be started including GraphQL server and fully
602    /// initialized. After 2 seconds the runtime will be stopped.
603    #[tokio::test(flavor = "multi_thread")]
604    async fn test_run() {
605        let stdout = ConsoleAppender::builder().build();
606        let config = Config::builder()
607            .appender(Appender::builder().build("stdout", Box::new(stdout)))
608            .build(Root::builder().appender("stdout").build(LevelFilter::Trace))
609            .expect("Failed to create logger");
610        if let Err(error) = log4rs::init_config(config) {
611            eprintln!("Failed to configure logger: {}", error);
612        }
613        let rt = get_runtime();
614        let runtime = rt.clone();
615        tokio::spawn(async move {
616            let runtime = runtime;
617            runtime.init().await;
618            runtime.post_init().await;
619            runtime.run().await;
620            runtime.pre_shutdown().await;
621            runtime.shutdown().await;
622        });
623        tokio::time::sleep(Duration::from_secs(2)).await;
624        rt.stop();
625    }
626}