Skip to main content

transaction_async

Function transaction_async 

Source
pub async fn transaction_async<C: ConnectionLike + Clone, K: ToRedisArgs, T: FromRedisValue, F: FnMut(C, Pipeline) -> Fut, Fut: Future<Output = Result<Option<T>, RedisError>>>(
    connection: C,
    keys: &[K],
    func: F,
) -> Result<T, RedisError>
Expand description

Executes a Redis transaction asynchronously by automatically watching keys and running a transaction loop until it succeeds. Similar to the synchronous transaction function but for async execution.

The provided closure may be executed multiple times if the transaction fails due to watched keys being modified between WATCH and EXEC. Any side effects in the closure should account for possible multiple executions. The closure should return Ok(None) to indicate a transaction failure and to retry (this will happen automatically if the last call in the closure is to run the transaction), or Err(err) to abort the transaction with an error. A successful transaction should return Ok(Some(value)) with the desired result from the EXEC command.

§Examples

use redis::{AsyncCommands, RedisResult, pipe};

async fn increment(con: redis::aio::MultiplexedConnection) -> RedisResult<isize> {
    let key = "my_counter";
    redis::aio::transaction_async(con, &[key], |mut con, mut pipe| async move {
        // Read the current value first
        let val: isize = con.get(key).await?;
        // Build the pipeline and execute it atomically (MULTI/EXEC are added automatically)
        pipe.set(key, val + 1)
            .ignore()
            .get(key)
            .query_async(&mut con)
            .await
    })
    .await
}

§Notes

  • The closure may be executed multiple times if watched keys are modified by other clients between WATCH and EXEC; its side effects must be idempotent.
  • A successful EXEC automatically discards all WATCHes, so no explicit UNWATCH is needed on the success path.
  • The transaction is automatically abandoned if the closure returns an error; an explicit UNWATCH is sent in that case to leave the connection in a clean state.

§Warning: Concurrent Transactions on Multiplexed Connections

When using a multiplexed connection (e.g. async connection types in this crate), cloning shares the underlying channel. Running concurrent transactions on clones of the same multiplexed connection could lead to unexpected behavior: the WATCH/MULTI/EXEC sequence from one transaction may interleave with commands from another. Ensure at most one transaction is active on a given multiplexed connection at a time.

§Warning: Transactions on cluster connections

A cluster connection is a collection of multiple underlying connections to different cluster nodes. Running a transaction on a cluster connection is only safe if all the keys being watched and modified in the transaction are guaranteed to be on the same cluster node, since Redis transactions cannot span multiple nodes. It is the caller’s responsibility to ensure this condition is met when using transaction_async with a cluster connection.

For more details on Redis transactions, see the Redis documentation