Crate transaction

Source
Expand description

§Zero-cost transaction abstraction in Rust

This crate abstracts over transactions like STM, SQL transactions and so on. It is composable via combinators and does DI of transactions.

The basic idea is representing contracts of “this computation must be run” as types. The trait Transaction represents o sequence of computation that must be run under a transaction. And transactions are composable (sequencable) using then, and_then, or_else, hence you can use it like values wrapped in Result.Since it represents computation to be run in data, some types respond to control operators are provided: abort for ?, repeat for for, loop_fn for loop and branch for (join point of) if and so on. As all the combinators have its own result type, no dispatches are done at execution time thus it is zero-cost.

Another feature is it does DI of transaction. For database transaction, it means it injects DB connection from the context.

§Examples


extern crate transaction;

use self::transaction::prelude::*;


// Since current rust doesn't support `impl Trait`, you need to make a
// trait box
// to return a trait value from a function.
type BoxTx<'a, T> = Box<Transaction<
                          Ctx = FooConnection,
                          Item = T,
                          Err =FooError>
                        + 'a>;

fn find_user<'a>(id: i64) -> BoxTx<'a, Option<User>> {
    // connection is inejected from the context
    with_ctx(move |cn: &mut FooConnection| {
        // ..
    }).boxed()

}

fn update_user<'a>(id: i64, name: &'a str) -> BoxTx<'a, Option<()>> {
    with_ctx(move |cn: &mut FooConnection| {
        // ..
    }).boxed()
}

fn update_find_user<'a>(id: i64, name: &'a str) -> BoxTx<'a, Option<User>> {
    update_user(id, name)
        // transaction can be composed using `and_then`
        .and_then(move |ret| match ret {
            None =>
                // to return a leaf transaction, use `ok`, `err` or `result`
                ok(None)
                // to return from a branch (or, to match types at join
                // point), use `branch` API
                .branch()
                // use `first` in the first arm of the brnach
                .first(),
            Some(()) => find_user(id)
                .branch()
                // use `second` in the second arm of the brnach
                .second(),
        })
        // finally, box it to return `BoxTx`.
        .boxed()
}

Modules§

prelude

Structs§

Abort
The result of abort
AndThen
The result of and_then
Branch3Builder
Branch3Builder
Branch4Builder
Branch4Builder
BranchBuilder
BranchBuilder
Join
The result of join
Join3
The result of join3
Join4
The result of join4
JoinAll
The result of join_vec
Lazy
The result of lazy
LoopFn
The result of loop_fn
Map
The result of map
MapErr
The result of map_err
OrElse
The result of or_else
Recover
The result of recover
Repeat
The result of repeat
Retry
The result of retry
Then
The result of then
TryAbort
TryRecover
The result of try_recover
TxErr
The result of err
TxOk
The result of ok
TxResult
The result of result
WithCtx
The result of with_ctx

Enums§

Branch
The result of branch
Branch3
The result of branch3
Branch4
The result of branch4
Loop
The status of a loop_fn loop.

Traits§

IntoTransaction
types than can be converted into transaction
Transaction
An abstract transaction. Transactions sharing the same Ctx can be composed with combinators. When the transaction return an error, it means the transaction is failed. Some runners may abort the transaction and the other may retry the computation. Thus all the computation should be idempotent (of cause, except operations using context). Note that this transaction is not executed until it is run.

Functions§

abort
Take the previous successfull value of computation and abort the transaction.
and_then
err
make a error transaction value.
join
join3
join4
join_all
join a vec of transaction
lazy
lazy evaluated transaction value. Note that inner function can be called many times.
loop_fn
map
map_err
ok
make a successful transaction value.
or_else
recover
repeat
result
Take a result and make a leaf transaction value.
retry
then
try_abort
try_recover
with_ctx
Receive the context from the executing transaction and perform computation.