From b7973dc18d8b749e2a7dc0547c008eb446c6eab7 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Tue, 3 Feb 2026 19:42:55 +0100 Subject: [PATCH] feat: add basic retry handling --- Cargo.lock | 7 +++++++ crates/noretry/Cargo.toml | 1 + crates/noretry/src/lib.rs | 18 ++++++++++++++---- crates/noretry/tests/mod.rs | 13 +++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3bcbcf..2c81d75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/crates/noretry/Cargo.toml b/crates/noretry/Cargo.toml index bf403b3..c2b5139 100644 --- a/crates/noretry/Cargo.toml +++ b/crates/noretry/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] anyhow.workspace = true +either = "1.15.0" thiserror = "2.0.18" tokio.workspace = true tracing.workspace = true diff --git a/crates/noretry/src/lib.rs b/crates/noretry/src/lib.rs index b0ec1cc..d63e408 100644 --- a/crates/noretry/src/lib.rs +++ b/crates/noretry/src/lib.rs @@ -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( mut self, f: T, - ) -> Result, RetryError> + ) -> Result> where T: Fn() -> TFut + Send + 'static, TFut: Future>, { - 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, +} diff --git a/crates/noretry/tests/mod.rs b/crates/noretry/tests/mod.rs index 7fadc74..e1e2519 100644 --- a/crates/noretry/tests/mod.rs +++ b/crates/noretry/tests/mod.rs @@ -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 { println!("my func was called"); Ok("output".into()) } + +async fn fail() -> anyhow::Result { + anyhow::bail!("fails") +}