Crate transaction [] [src]

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.