use std::{future::Future, time::Duration};
use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]
#[error("operation timed out after {duration:?}")]
pub struct TimeoutError {
pub duration: Duration,
}
pub async fn run_with_timeout<F, T>(duration: Duration, future: F) -> Result<T, TimeoutError>
where
F: Future<Output = T>,
{
tokio::time::timeout(duration, future)
.await
.map_err(|_| TimeoutError { duration })
}
#[cfg(test)]
mod tests {
use super::run_with_timeout;
use std::time::Duration;
#[tokio::test]
async fn returns_value_before_timeout() {
let value = run_with_timeout(Duration::from_millis(50), async { 7 })
.await
.expect("value");
assert_eq!(value, 7);
}
#[tokio::test]
async fn returns_timeout_error() {
let result = run_with_timeout(Duration::from_millis(5), async {
tokio::time::sleep(Duration::from_millis(50)).await;
})
.await;
assert!(result.is_err());
}
}