Skip to main content

BeginExt

Trait BeginExt 

Source
pub trait BeginExt: Begin {
    // Provided method
    fn within<T, E, F>(&self, f: F) -> impl Future<Output = Result<T, E>>
       where F: AsyncFnOnce(&Transaction) -> Result<T, E>,
             E: From<ExecError> { ... }
}
Expand description

The closure form of a transaction: commit on Ok, roll back on Err.

The closure receives &Transaction and so cannot commit or consume it — within owns the outcome. Neither a dropped transaction nor a forgotten commit is expressible here, which is why this is the recommended shape.

§within or Atomic::atomic

On a pool they are the same call: atomic for a Begin is within. What differs is what the receiver may be, which is to say what the code claims:

  • within takes a Begin and nothing else — a transaction begins here. Handing it a Transaction does not compile.
  • atomic takes either — I do not care which of the two this is, I care that it is atomic.

The weaker claim is not the safer default. Anything whose correctness depends on where the transaction ends needs within:

  • A retry loop. Re-running a savepoint cannot clear a serialization failure — the snapshot is unchanged, so the conflict recurs. A retry written against atomic would spin when its caller happened to be inside a transaction; written against within, that call does not compile.
  • Isolation and access mode, which are properties of the outermost transaction and so are only reachable through BeginWith::begin_with and BeginWithExt::within_with.

Rule of thumb: within when the extent of the transaction is part of what the code is saying, atomic for a reusable unit of work that only needs its own block to be all-or-nothing.

Provided Methods§

Source

fn within<T, E, F>(&self, f: F) -> impl Future<Output = Result<T, E>>
where F: AsyncFnOnce(&Transaction) -> Result<T, E>, E: From<ExecError>,

Run f inside a fresh transaction.

let order = db.within(async |tx| {
    let order: Order = insert_order.fetch_one(tx).await?;
    reserve_stock(tx, &order).await?;
    Ok(order)
}).await?;

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<B: Begin + ?Sized> BeginExt for B