feat: add basic retry handling
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -32,6 +32,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
@@ -79,6 +85,7 @@ name = "noretry"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"either",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
|
||||
@@ -5,6 +5,7 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
either = "1.15.0"
|
||||
thiserror = "2.0.18"
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use either::Either;
|
||||
|
||||
pub fn builder() -> RetryBuilder {
|
||||
RetryBuilder {
|
||||
max_attempts: Some(3),
|
||||
@@ -48,16 +52,22 @@ impl RetryOptions {
|
||||
pub async fn run<T, TFut, TOk, TError>(
|
||||
mut self,
|
||||
f: T,
|
||||
) -> Result<Result<TOk, TError>, RetryError>
|
||||
) -> Result<TOk, Either<TError, RetryError>>
|
||||
where
|
||||
T: Fn() -> TFut + Send + 'static,
|
||||
TFut: Future<Output = Result<TOk, TError>>,
|
||||
{
|
||||
let res = f().await;
|
||||
match f().await {
|
||||
Ok(success) => return Ok(success),
|
||||
Err(e) => return Err(either::Left(e)),
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
Err(either::Right(RetryError::ExhaustedAttempts))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum RetryError {}
|
||||
pub enum RetryError {
|
||||
#[error("retry stopped because attempts exceeded budget")]
|
||||
ExhaustedAttempts,
|
||||
}
|
||||
|
||||
@@ -7,8 +7,21 @@ async fn test_can_call() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_can_fail() -> anyhow::Result<()> {
|
||||
let res = noretry::builder().build().run(fail).await?;
|
||||
|
||||
assert_eq!("output", res.as_str());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn my_func() -> anyhow::Result<String> {
|
||||
println!("my func was called");
|
||||
|
||||
Ok("output".into())
|
||||
}
|
||||
|
||||
async fn fail() -> anyhow::Result<String> {
|
||||
anyhow::bail!("fails")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user