From: Stefan Reiter <s.reiter@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [RFC proxmox 1/2] add tools::future with TimeoutFutureExt
Date: Mon, 21 Dec 2020 14:56:10 +0100 [thread overview]
Message-ID: <20201221135611.14456-2-s.reiter@proxmox.com> (raw)
In-Reply-To: <20201221135611.14456-1-s.reiter@proxmox.com>
Implements shorthands to automatically cancel a long-running future
after a timeout is reached.
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
proxmox/src/tools/future.rs | 48 +++++++++++++++++++++++++++++++++++++
proxmox/src/tools/mod.rs | 1 +
2 files changed, 49 insertions(+)
create mode 100644 proxmox/src/tools/future.rs
diff --git a/proxmox/src/tools/future.rs b/proxmox/src/tools/future.rs
new file mode 100644
index 0000000..476fd11
--- /dev/null
+++ b/proxmox/src/tools/future.rs
@@ -0,0 +1,48 @@
+//! Common extensions for Futures
+use anyhow::Error;
+use futures::future::{select, Either, FutureExt};
+use std::future::Future;
+use std::time::Duration;
+use tokio::time::delay_for;
+
+impl<T> TimeoutFutureExt for T where T: Future {}
+
+/// Implements a timeout for futures, automatically aborting them if the timeout runs out before
+/// the base future completes.
+pub trait TimeoutFutureExt: Future {
+ /// Returned Future returns 'None' in case the timeout was reached, otherwise the original
+ /// return value.
+ fn or_timeout<'a>(
+ self,
+ timeout: Duration,
+ ) -> Box<dyn Future<Output = Option<Self::Output>> + Unpin + Send + 'a>
+ where
+ Self: Sized + Unpin + Send + 'a,
+ {
+ let timeout_fut = delay_for(timeout);
+ Box::new(select(self, timeout_fut).map(|res| match res {
+ Either::Left((result, _)) => Some(result),
+ Either::Right(((), _)) => None,
+ }))
+ }
+
+ /// Returned Future returns either the original result, or `Err<err>` in case the timeout is
+ /// reached. Basically a shorthand to flatten a future that returns a `Result<_, Error>` with a
+ /// timeout. The base Future can return any kind of Error that can be made into an
+ /// `anyhow::Error`.
+ fn or_timeout_err<'a, O, E>(
+ self,
+ timeout: Duration,
+ err: Error,
+ ) -> Box<dyn Future<Output = Result<O, Error>> + Unpin + Send + 'a>
+ where
+ Self: Sized + Unpin + Send + 'a,
+ Self::Output: Into<Result<O, E>>,
+ E: Into<Error> + std::error::Error + Send + Sync + 'static,
+ {
+ Box::new(self.or_timeout(timeout).map(|res| match res {
+ Some(res) => res.into().map_err(Error::from),
+ None => Err(err),
+ }))
+ }
+}
diff --git a/proxmox/src/tools/mod.rs b/proxmox/src/tools/mod.rs
index ff3a720..5d1f46e 100644
--- a/proxmox/src/tools/mod.rs
+++ b/proxmox/src/tools/mod.rs
@@ -20,6 +20,7 @@ pub mod serde;
pub mod time;
pub mod uuid;
pub mod vec;
+pub mod future;
#[cfg(feature = "websocket")]
pub mod websocket;
--
2.20.1
next prev parent reply other threads:[~2020-12-21 13:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-21 13:56 [pbs-devel] [RFC 0/2] backup client: implement some HTTP timeouts Stefan Reiter
2020-12-21 13:56 ` Stefan Reiter [this message]
2020-12-21 13:56 ` [pbs-devel] [RFC proxmox-backup 2/2] http_client: add timeouts for critical connects Stefan Reiter
2020-12-21 15:36 ` [pbs-devel] [RFC 0/2] backup client: implement some HTTP timeouts Dietmar Maurer
2020-12-21 15:45 ` Dietmar Maurer
2020-12-21 15:49 ` Stefan Reiter
2020-12-21 16:40 ` Dietmar Maurer
2020-12-22 8:47 ` Stefan Reiter
2020-12-22 10:40 ` Dietmar Maurer
2020-12-22 12:32 ` [pbs-devel] applied: " Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201221135611.14456-2-s.reiter@proxmox.com \
--to=s.reiter@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.