use shape_ast::error::{Result, ShapeError};
use std::future::Future;
use std::sync::{Arc, OnceLock};
use tokio::runtime::{Handle, Runtime};
static SHARED_RUNTIME: OnceLock<Arc<Runtime>> = OnceLock::new();
pub fn initialize_shared_runtime() -> Result<()> {
if SHARED_RUNTIME.get().is_some() {
return Ok(()); }
let runtime = Runtime::new().map_err(|e| ShapeError::RuntimeError {
message: format!("Failed to create shared Tokio runtime: {}", e),
location: None,
})?;
SHARED_RUNTIME
.set(Arc::new(runtime))
.map_err(|_| ShapeError::RuntimeError {
message: "Failed to set shared runtime (race condition)".to_string(),
location: None,
})?;
Ok(())
}
pub fn get_runtime_handle() -> Result<Handle> {
let runtime = SHARED_RUNTIME
.get()
.ok_or_else(|| ShapeError::RuntimeError {
message: "Shared runtime not initialized. Call initialize_shared_runtime() first."
.to_string(),
location: None,
})?;
Ok(runtime.handle().clone())
}
pub fn block_on_shared<F, T>(future: F) -> Result<T>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
let handle = get_runtime_handle()?;
let result = if let Ok(_handle_in_runtime) = Handle::try_current() {
let (tx, rx) = std::sync::mpsc::channel();
handle.spawn(async move {
let result = future.await;
let _ = tx.send(result);
});
rx.recv().map_err(|e| ShapeError::RuntimeError {
message: format!("Failed to receive async result: {}", e),
location: None,
})?
} else {
handle.block_on(future)
};
Ok(result)
}
#[derive(Clone)]
pub struct SyncDataProvider {
_placeholder: std::marker::PhantomData<()>,
}