PostgreSQL / CockroachDB Async Transaction Retries for Rust

Asynchronous and synchronous Postgres protocol transaction retries.

Providing a mechanism for serialized transaction retries for PostgresSQL compatible databases in Rust.

Error Type Requirements

The closure over the transaction must return an error that implements Into<postgres_tx_retry::Error<E>> and for serialization failure determination, your error type should implement (depending on enabled features):

A basic error type might be:

```rust pub enum MyError { Pool(deadpool::managed::PoolError), Postgres(tokio_postgres::Error), R2d2(r2d2::Error), Message(&'static str), }

impl Into> for MyError { fn into(self) -> postgrestxretry::Error { match self { Self::Pool(e) => postgrestxretry::Error::Pool(e), Self::Postgres(e) => postgrestxretry::Error::Postgres(e), Self::R2d2(e) => postgrestxretry::Error::R2d2(e), _ => postgrestxretry::Error::Other(self), } } }

impl From> for MyError where E: Into, { fn from(src: postgrestxretry::Error) -> Self { match src { postgrestxretry::Error::Pool(e) => Self::Pool(e), postgrestxretry::Error::Postgres(e) => Self::Postgres(e), postgrestxretry::Error::R2d2(e) => Self::R2d2(e), postgrestxretry::Error::Other(e) => e.into(), } } } ```

Asynchronous Example

```rust let values = Arc::new("London"); let population = tx(&pool, COCKROACH_SAVEPOINT, |tx| { let values = values.clone();

Box::pin(async move {
    let name = values.as_ref();
    let row = tx
        .query_one(
            "SELECT population FROM city WHERE name = $1",
            &[&name],
        )
        .await?;

    Ok(row.get(0))
})

}) .await?; ```

Synchronous Example

```rust let name = "London"; let population = txsync(&db, COCKROACHSAVEPOINT, |tx| { let row = tx.query_one( "SELECT population FROM city WHERE name = $1", &[&name], )?;

Ok(row.get(0))

})?; ```