feat: add basic retry handling

This commit is contained in:
2026-02-03 19:42:55 +01:00
parent c5feb88d5c
commit b7973dc18d
4 changed files with 35 additions and 4 deletions

7
Cargo.lock generated
View File

@@ -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",

View File

@@ -5,6 +5,7 @@ edition = "2024"
[dependencies]
anyhow.workspace = true
either = "1.15.0"
thiserror = "2.0.18"
tokio.workspace = true
tracing.workspace = true

View File

@@ -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,
}

View File

@@ -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")
}