Xuanwo/backon

Use with sqlx?

Closed this issue · 2 comments

Hey!

The library seems pretty cool! I am new to rust, trying to implement a retry strategy on a small rest API project. Could you help me understand how to use it?

I am trying to implement a retry strategy on a SQLx query. If it fails I want to retry it before returning a 5xx error.

I would normally run the code such as:

query
    .execute(pool.inner())
    .await

Now, with backon;
This doesn't work -

query
    .execute(pool.inner())
    .retry(&ExponentialBuilder::default())
    .await

Error:

| error[E0599]: the method `retry` exists for opaque type `impl Future<Output = Result<<Postgres as Database>::QueryResult, Error>>`, but its trait bounds were not satisfied
|    --> src/model/user/create.rs:105:10
|     |
| 103 |       let rows_affected = query
|     |  _________________________-
| 104 | |         .execute(pool.inner())
| 105 | |         .retry(&ExponentialBuilder::default())
|     | |         -^^^^^ method cannot be called due to unsatisfied trait bounds
|     | |_________|
|     | 
|     |
|     = note: the following trait bounds were not satisfied:
|             `<impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>> as FnOnce<(_,)>>::Output = _`
|             which is required by `impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`
|             `impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: FnMut<(_,)>`
|             which is required by `impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`
|             `<&impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>> as FnOnce<(_,)>>::Output = _`
|             which is required by `&impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, &impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`
|             `&impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: FnMut<(_,)>`
|             which is required by `&impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, &impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`
|             `<&mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>> as FnOnce<(_,)>>::Output = _`
|             which is required by `&mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, &mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`
|             `&mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: FnMut<(_,)>`
|             which is required by `&mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>: RetryableWithContext<_, _, _, _, _, &mut impl std::future::Future<Output = Result<<Postgres as sqlx::Database>::QueryResult, sqlx::Error>>>`

And using a lamba doesn't seem to work either:

{
        || async {
            let connection = pool.acquire().await.map_err(anyhow::Error::from)?;
            query.execute(connection).await.map_err(anyhow::Error::from)
        }
    }
        .retry(&ExponentialBuilder::default())
        .await?;

Error:

| error[E0277]: the trait bound `sqlx::pool::PoolConnection<Postgres>: Executor<'_>` is not satisfied
|    --> src/model/user/create.rs:105:27
|     |
| 105 |             query.execute(connection).await.map_err(anyhow::Error::from)
|     |                   ------- ^^^^^^^^^^ the trait `Executor<'_>` is not implemented for `sqlx::pool::PoolConnection<Postgres>`
|     |                   |
|     |                   required by a bound introduced by this call
|     |
|     = help: the following other types implement trait `Executor<'c>`:
|               <&'c mut PgConnection as Executor<'c>>
|               <&'c mut PgListener as Executor<'c>>
|               <&'c mut AnyConnection as Executor<'c>>
|               <&Pool<DB> as Executor<'p>>
| note: required by a bound in `sqlx::query::Query::<'q, DB, A>::execute`
|    --> /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/sqlx-core-0.7.4/src/query.rs:155:12
|     |
| 151 |     pub async fn execute<'e, 'c: 'e, E>(self, executor: E) -> Result<DB::QueryResult, Error>
|     |                  ------- required by a bound in this associated function
| ...
| 155 |         E: Executor<'c, Database = DB>,
|     |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Query::<'q, DB, A>::execute`

Hi, I plan to add an example for sqlx. Please keep tuned.

Hi, @alexisgaziello, I have added an example for sqlite: #91