use rig_http::{http_client::Error, wasm_compat::WasmCompatSend};
use std::future::Future;
use std::sync::LazyLock;
use tokio::runtime::{Handle, Runtime};
use tokio::task::JoinHandle;
static RUNTIME: LazyLock<Result<Runtime, RuntimeUnavailable>> = LazyLock::new(|| {
tokio::runtime::Builder::new_multi_thread()
.worker_threads(1)
.thread_name("rig-tungstenite")
.enable_all()
.build()
.map_err(|err| RuntimeUnavailable(err.to_string()))
});
#[derive(Debug, Clone, thiserror::Error)]
#[error("rig-tungstenite: failed to start the fallback tokio runtime: {0}")]
struct RuntimeUnavailable(String);
fn runtime() -> Result<&'static Runtime, Error> {
RUNTIME.as_ref().map_err(|err| Error::instance(err.clone()))
}
pub(crate) fn in_tokio() -> bool {
Handle::try_current().is_ok()
}
pub(crate) struct OwnedTask<T> {
handle: JoinHandle<T>,
}
impl<T> OwnedTask<T> {
pub(crate) async fn join(mut self) -> Result<T, Error> {
(&mut self.handle).await.map_err(Error::instance)
}
}
impl<T> Drop for OwnedTask<T> {
fn drop(&mut self) {
self.handle.abort();
}
}
pub(crate) async fn run_off_runtime<F>(future: F) -> Result<F::Output, Error>
where
F: Future + WasmCompatSend + 'static,
F::Output: WasmCompatSend + 'static,
{
spawn_off_runtime(future)?.join().await
}
pub(crate) fn spawn_off_runtime<F>(future: F) -> Result<OwnedTask<F::Output>, Error>
where
F: Future + WasmCompatSend + 'static,
F::Output: WasmCompatSend + 'static,
{
Ok(OwnedTask {
handle: runtime()?.spawn(future),
})
}