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§
Structs§
- Abort
- The result of
abort
- AndThen
- The result of
and_then
- Branch3
Builder - Branch3Builder
- Branch4
Builder - Branch4Builder
- Branch
Builder - 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§
- Into
Transaction - 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 isrun
.
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.