【问题标题】:How to race collection of futures in Rust and with retry如何在 Rust 中竞速收集期货并重试
【发布时间】:2022-12-12 18:20:42
【问题描述】:
我有一个 Futures 集合,我想执行所有 Futures 并获得第一个成功解析并中止其他仍在处理中的 Futures 。
但我想处理第一个解决的未来实际返回无效值的情况,从而导致需要重试的情况。
我从 tokio 找到了 select! 宏,但它不支持竞速一系列期货。使用 select! 需要明确列出将要比赛的期货......使其不适用于我的用例。我也没有看到它支持任何重试机制。
那么我如何在 Rust 中竞速收集 futures 并重试呢?
【问题讨论】:
标签:
rust
async-await
rust-tokio
【解决方案1】:
如果你的期货返回Result,你需要在Err上重试,“重试”并不是要重试失败的期货,而是要尝试其他期货,你可以使用futures'select_ok():
async fn first_successful<T, E: fmt::Debug, Fut>(futures: Vec<Fut>) -> T
where
E: fmt::Debug,
Fut: Future<Output = Result<T, E>> + Unpin,
{
let (output, _remaining_futures) = futures::future::select_ok(futures)
.await
.expect("all futures failed");
output
}
如果没有,你需要更多的控制,你可以使用强大的FuturesUnordered。例如,使用自定义谓词尝试其他人:
use futures::stream::StreamExt;
async fn first_successful<Fut: Future + Unpin>(
futures: Vec<Fut>,
mut failed: impl FnMut(&Fut::Output) -> bool,
) -> Fut::Output {
let mut futures = futures::stream::FuturesUnordered::from_iter(futures);
while let Some(v) = futures.next().await {
if !failed(&v) {
return v;
}
}
panic!("all futures failed");
}