use std::future::Future;
use std::sync::Mutex;
use std::time::Duration;
use wind_tunnel_core::prelude::{ShutdownHandle, ShutdownSignalError};
#[derive(Debug)]
pub struct Executor {
handle: tokio::runtime::Handle,
runtime: Mutex<Option<tokio::runtime::Runtime>>,
shutdown_handle: ShutdownHandle,
}
impl Executor {
pub(crate) fn new(runtime: tokio::runtime::Runtime, shutdown_handle: ShutdownHandle) -> Self {
let handle = runtime.handle().clone();
Self {
handle,
runtime: Mutex::new(Some(runtime)),
shutdown_handle,
}
}
pub fn execute_in_place<T>(
&self,
fut: impl Future<Output = anyhow::Result<T>>,
) -> anyhow::Result<T> {
let mut shutdown_listener = self.shutdown_handle.new_listener();
self.handle.block_on(async move {
tokio::select! {
result = fut => result,
_ = shutdown_listener.wait_for_shutdown() => {
Err(anyhow::anyhow!(ShutdownSignalError::default()))
},
}
})
}
pub fn spawn(&self, fut: impl Future<Output = ()> + Send + 'static) {
self.handle.spawn(fut);
}
pub(crate) fn shutdown_with_timeout(&self, timeout: Duration) {
if let Some(runtime) = self.runtime.lock().unwrap().take() {
runtime.shutdown_timeout(timeout);
}
}
}