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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
@@ -79,6 +85,7 @@ name = "noretry"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"either",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
either = "1.15.0"
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use either::Either;
|
||||||
|
|
||||||
pub fn builder() -> RetryBuilder {
|
pub fn builder() -> RetryBuilder {
|
||||||
RetryBuilder {
|
RetryBuilder {
|
||||||
max_attempts: Some(3),
|
max_attempts: Some(3),
|
||||||
@@ -48,16 +52,22 @@ impl RetryOptions {
|
|||||||
pub async fn run<T, TFut, TOk, TError>(
|
pub async fn run<T, TFut, TOk, TError>(
|
||||||
mut self,
|
mut self,
|
||||||
f: T,
|
f: T,
|
||||||
) -> Result<Result<TOk, TError>, RetryError>
|
) -> Result<TOk, Either<TError, RetryError>>
|
||||||
where
|
where
|
||||||
T: Fn() -> TFut + Send + 'static,
|
T: Fn() -> TFut + Send + 'static,
|
||||||
TFut: Future<Output = Result<TOk, TError>>,
|
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)]
|
#[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(())
|
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> {
|
async fn my_func() -> anyhow::Result<String> {
|
||||||
println!("my func was called");
|
println!("my func was called");
|
||||||
|
|
||||||
Ok("output".into())
|
Ok("output".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fail() -> anyhow::Result<String> {
|
||||||
|
anyhow::bail!("fails")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user