use std::time::Duration;
use tokio::time::{Timeout, timeout};
pub fn with_timeout<F>(future: F, duration: Duration) -> Timeout<F>
where
F: std::future::Future,
{
timeout(duration, future)
}
pub const DEFAULT_NETWORK_TIMEOUT: Duration = Duration::from_secs(30);
pub const DEFAULT_STORAGE_TIMEOUT: Duration = Duration::from_secs(10);
pub const DEFAULT_RPC_TIMEOUT: Duration = Duration::from_secs(60);
pub async fn with_network_timeout<F, T>(operation: F) -> Result<T, tokio::time::error::Elapsed>
where
F: std::future::Future<Output = T>,
{
timeout(DEFAULT_NETWORK_TIMEOUT, operation).await
}
pub async fn with_storage_timeout<F, T>(operation: F) -> Result<T, tokio::time::error::Elapsed>
where
F: std::future::Future<Output = T>,
{
timeout(DEFAULT_STORAGE_TIMEOUT, operation).await
}
pub async fn with_rpc_timeout<F, T>(operation: F) -> Result<T, tokio::time::error::Elapsed>
where
F: std::future::Future<Output = T>,
{
timeout(DEFAULT_RPC_TIMEOUT, operation).await
}
pub async fn with_custom_timeout<F, T>(
operation: F,
duration: Duration,
) -> Result<T, tokio::time::error::Elapsed>
where
F: std::future::Future<Output = T>,
{
timeout(duration, operation).await
}
#[inline]
pub fn storage_timeout_from_config(
config: Option<&crate::config::RequestTimeoutConfig>,
) -> Duration {
config
.map(|c| Duration::from_secs(c.storage_timeout_seconds))
.unwrap_or(DEFAULT_STORAGE_TIMEOUT)
}
#[inline]
pub fn rpc_timeout_from_config(config: Option<&crate::config::RequestTimeoutConfig>) -> Duration {
config
.map(|c| Duration::from_secs(c.rpc_timeout_seconds))
.unwrap_or(DEFAULT_RPC_TIMEOUT)
}
#[inline]
pub fn handshake_timeout_from_config(
config: Option<&crate::config::RequestTimeoutConfig>,
) -> Duration {
config
.map(|c| Duration::from_secs(c.handshake_timeout_secs))
.unwrap_or(Duration::from_secs(10))
}
#[cfg(test)]
mod network_timeout_field_tests {
use std::path::Path;
fn needle() -> String {
format!("{}{}", "network_timeout_", "seconds")
}
fn walk(dir: &Path, hits: &mut Vec<String>) {
let entries = std::fs::read_dir(dir).unwrap();
for entry in entries {
let path = entry.unwrap().path();
if path.is_dir() {
walk(&path, hits);
} else if let Ok(text) = std::fs::read_to_string(&path) {
if text.contains(&needle()) {
hits.push(path.display().to_string());
}
}
}
}
#[test]
fn network_timeout_field_is_not_in_src() {
let src = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
let mut hits = Vec::new();
walk(&src, &mut hits);
assert!(
hits.is_empty(),
"src still names the removed field: {hits:?}"
);
let config = std::fs::read_to_string(src.join("config/mod.rs")).unwrap();
assert!(config.contains("connect_timeout_secs"));
assert!(config.contains("handshake_timeout_secs"));
assert!(config.contains("async_request_timeout_seconds"));
assert!(config.contains("rpc_timeout_seconds"));
let timeouts = std::fs::read_to_string(src.join("utils/timeout.rs")).unwrap();
assert!(timeouts.contains("fn rpc_timeout_from_config"));
assert!(timeouts.contains("pub async fn with_network_timeout"));
assert!(timeouts.contains("DEFAULT_NETWORK_TIMEOUT: Duration = Duration::from_secs(30)"));
}
}