Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use wasm-compatible sleep if compiled for wasm32 #92

Merged
merged 7 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,14 @@ jobs:
env:
RUST_LOG: DEBUG
RUST_BACKTRACE: full

wasm-unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- run: wasm-pack test --node
env:
RUST_LOG: DEBUG
RUST_BACKTRACE: full
23 changes: 21 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,27 @@ version = "0.4.4"
fastrand = "2.0.0"
tokio = { version = "1", features = ["time"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
gloo-timers = { version = "0.3", features = ["futures"] }

[dev-dependencies]
anyhow = "1"
reqwest = "0.12"
tokio = { version = "1", features = ["time", "rt", "macros", "sync", "rt-multi-thread"] }
sqlx = { version = "0.8.0", features = ["runtime-tokio", "sqlite"] }

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
tokio = { version = "1", features = [
"macros",
"rt",
"sync",
], default-features = false }
wasm-bindgen-test = "0.3"

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
sqlx = { version = "0.8.0", features = ["runtime-tokio", "sqlite"] }
tokio = { version = "1", features = [
"time",
"rt",
"macros",
"sync",
"rt-multi-thread",
] }
11 changes: 8 additions & 3 deletions examples/blocking.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use anyhow::Result;
use backon::BlockingRetryable;
use backon::ExponentialBuilder;

// For more examples, please see: https://docs.rs/backon/#examples

fn fetch() -> Result<String> {
Ok("hello, world!".to_string())
}

// this example does not run on wasm32-unknown-unknown
#[cfg(not(target_arch = "wasm32"))]
fn main() -> Result<()> {
let content = fetch.retry(&ExponentialBuilder::default()).call()?;
use backon::BlockingRetryable;

let content = fetch.retry(&backon::ExponentialBuilder::default()).call()?;
println!("fetch succeeded: {}", content);

Ok(())
}

#[cfg(target_arch = "wasm32")]
fn main() {}
15 changes: 9 additions & 6 deletions examples/closure.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use anyhow::Result;
use backon::BlockingRetryable;
use backon::ExponentialBuilder;

// For more examples, please see: https://docs.rs/backon/#examples

fn main() -> Result<()> {
// this example does not run on wasm32-unknown-unknown
#[cfg(not(target_arch = "wasm32"))]
fn main() -> anyhow::Result<()> {
use backon::BlockingRetryable;

let var = 42;
// `f` can use input variables
let f = || Ok::<u32, anyhow::Error>(var);
let result = f.retry(&ExponentialBuilder::default()).call()?;
let result = f.retry(&backon::ExponentialBuilder::default()).call()?;
println!("var = {result}");

Ok(())
}

#[cfg(target_arch = "wasm32")]
fn main() {}
18 changes: 11 additions & 7 deletions examples/sqlx.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
use anyhow::Result;
use backon::ExponentialBuilder;
use backon::Retryable;
use sqlx::sqlite::SqlitePoolOptions;
// For more examples, please see: https://docs.rs/backon/#examples

// this example does not run on wasm32-unknown-unknown
#[cfg(not(target_arch = "wasm32"))]
#[tokio::main]
async fn main() -> Result<()> {
let pool = SqlitePoolOptions::new()
async fn main() -> anyhow::Result<()> {
use backon::Retryable;

let pool = sqlx::sqlite::SqlitePoolOptions::new()
.max_connections(5)
.connect("sqlite::memory:")
.await?;

let row: (i64,) = (|| sqlx::query_as("SELECT $1").bind(150_i64).fetch_one(&pool))
.retry(&ExponentialBuilder::default())
.retry(&backon::ExponentialBuilder::default())
.await?;

assert_eq!(row.0, 150);

Ok(())
}

#[cfg(target_arch = "wasm32")]
fn main() {}
3 changes: 3 additions & 0 deletions src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ impl Iterator for ConstantBackoff {
mod tests {
use std::time::Duration;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

use crate::backoff::BackoffBuilder;
use crate::constant::ConstantBuilder;

Expand Down
3 changes: 3 additions & 0 deletions src/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ pub(crate) fn saturating_mul(d: Duration, rhs: f32) -> Duration {
mod tests {
use std::time::Duration;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

use crate::backoff::BackoffBuilder;
use crate::exponential::ExponentialBuilder;

Expand Down
3 changes: 3 additions & 0 deletions src/fibonacci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ impl Iterator for FibonacciBackoff {
mod tests {
use std::time::Duration;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

use crate::backoff::BackoffBuilder;
use crate::fibonacci::FibonacciBuilder;

Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,14 @@ pub use retry::Retryable;
mod retry_with_context;
pub use retry_with_context::RetryableWithContext;

#[cfg(not(target_arch = "wasm32"))]
mod blocking_retry;
#[cfg(not(target_arch = "wasm32"))]
pub use blocking_retry::BlockingRetry;
#[cfg(not(target_arch = "wasm32"))]
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved
pub use blocking_retry::BlockingRetryable;

#[cfg(not(target_arch = "wasm32"))]
mod blocking_retry_with_context;
#[cfg(not(target_arch = "wasm32"))]
pub use blocking_retry_with_context::BlockingRetryableWithContext;
24 changes: 18 additions & 6 deletions src/retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use std::task::Context;
use std::task::Poll;
use std::time::Duration;

#[cfg(not(target_arch = "wasm32"))]
use tokio::time::{sleep, Sleep};

#[cfg(target_arch = "wasm32")]
use gloo_timers::future::{sleep, TimeoutFuture as Sleep};

use crate::backoff::BackoffBuilder;
use crate::Backoff;

Expand Down Expand Up @@ -208,7 +214,7 @@ enum State<T, E, Fut: Future<Output = Result<T, E>>> {
Idle,
Polling(Fut),
// TODO: we need to support other sleeper
Sleeping(tokio::time::Sleep),
Sleeping(Sleep),
}

impl<B, T, E, Fut, FutureFn, RF, NF> Future for Retry<B, T, E, Fut, FutureFn, RF, NF>
Expand Down Expand Up @@ -253,7 +259,7 @@ where
None => return Poll::Ready(Err(err)),
Some(dur) => {
(this.notify)(&err, dur);
this.state = State::Sleeping(tokio::time::sleep(dur));
this.state = State::Sleeping(sleep(dur));
continue;
}
}
Expand Down Expand Up @@ -282,14 +288,20 @@ mod tests {

use tokio::sync::Mutex;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[cfg(not(target_arch = "wasm32"))]
use tokio::test;

use super::*;
use crate::exponential::ExponentialBuilder;

async fn always_error() -> anyhow::Result<()> {
Err(anyhow::anyhow!("test_query meets error"))
}

#[tokio::test]
#[test]
async fn test_retry() -> anyhow::Result<()> {
let result = always_error
.retry(&ExponentialBuilder::default().with_min_delay(Duration::from_millis(1)))
Expand All @@ -300,7 +312,7 @@ mod tests {
Ok(())
}

#[tokio::test]
#[test]
async fn test_retry_with_not_retryable_error() -> anyhow::Result<()> {
let error_times = Mutex::new(0);

Expand All @@ -325,7 +337,7 @@ mod tests {
Ok(())
}

#[tokio::test]
#[test]
async fn test_retry_with_retryable_error() -> anyhow::Result<()> {
let error_times = Mutex::new(0);

Expand All @@ -350,7 +362,7 @@ mod tests {
Ok(())
}

#[tokio::test]
#[test]
async fn test_fn_mut_when_and_notify() -> anyhow::Result<()> {
let mut calls_retryable: Vec<()> = vec![];
let mut calls_notify: Vec<()> = vec![];
Expand Down
22 changes: 16 additions & 6 deletions src/retry_with_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use std::task::Context;
use std::task::Poll;
use std::time::Duration;

#[cfg(not(target_arch = "wasm32"))]
use tokio::time::{sleep, Sleep};

#[cfg(target_arch = "wasm32")]
use gloo_timers::future::{sleep, TimeoutFuture as Sleep};

use crate::backoff::BackoffBuilder;
use crate::Backoff;

Expand Down Expand Up @@ -255,7 +261,7 @@ enum State<T, E, Ctx, Fut: Future<Output = (Ctx, Result<T, E>)>> {
Idle(Option<Ctx>),
Polling(Fut),
// TODO: we need to support other sleeper
Sleeping((Option<Ctx>, tokio::time::Sleep)),
Sleeping((Option<Ctx>, Sleep)),
}

impl<B, T, E, Ctx, Fut, FutureFn, RF, NF> Future for Retry<B, T, E, Ctx, Fut, FutureFn, RF, NF>
Expand Down Expand Up @@ -302,8 +308,7 @@ where
None => return Poll::Ready((ctx, Err(err))),
Some(dur) => {
(this.notify)(&err, dur);
this.state =
State::Sleeping((Some(ctx), tokio::time::sleep(dur)));
this.state = State::Sleeping((Some(ctx), sleep(dur)));
continue;
}
}
Expand Down Expand Up @@ -331,12 +336,17 @@ where
mod tests {
use std::time::Duration;

use anyhow::anyhow;
use anyhow::{anyhow, Result};
use tokio::sync::Mutex;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[cfg(not(target_arch = "wasm32"))]
use tokio::test;

use super::*;
use crate::exponential::ExponentialBuilder;
use anyhow::Result;

struct Test;

Expand All @@ -346,7 +356,7 @@ mod tests {
}
}

#[tokio::test]
#[test]
async fn test_retry_with_not_retryable_error() -> Result<()> {
let error_times = Mutex::new(0);

Expand Down
Loading