1pub mod error;
2pub use error::StateError;
3use std::future::Future;
4use std::sync::{Arc, OnceLock};
5use tokio::runtime::{Handle, Runtime};
6use tracing::debug;
7
8pub struct ScouterState {
10 pub runtime: Arc<Runtime>,
11}
12
13impl ScouterState {
14 fn new() -> Result<Self, StateError> {
16 debug!("Initializing ScouterState (Multi-threaded Runtime)");
17 let runtime = Arc::new(
18 tokio::runtime::Builder::new_multi_thread() .enable_all()
20 .build()
21 .map_err(StateError::RuntimeError)?,
22 );
23 Ok(Self { runtime })
24 }
25
26 pub fn handle(&self) -> Handle {
28 self.runtime.handle().clone()
29 }
30
31 pub fn block_on<F, T>(&self, future: F) -> T
34 where
35 F: std::future::Future<Output = T>,
36 {
37 self.runtime.block_on(future)
38 }
39}
40
41static INSTANCE: OnceLock<ScouterState> = OnceLock::new();
43
44pub fn app_state() -> &'static ScouterState {
46 INSTANCE.get_or_init(|| ScouterState::new().expect("Failed to initialize state"))
47}
48
49pub fn block_on<F: Future>(future: F) -> F::Output {
51 app_state().block_on(future)
52}