#抽象 #计算 #连接 #中止 #分支 #重复 #上下文

transaction

事务抽象库(即事务函子)

2 个不稳定版本

使用旧的 Rust 2015

0.2.1 2017年6月23日
0.2.0 2017年6月21日
0.1.0 2017年6月6日

#2001Rust 模式


2 个 crate 中使用

MIT 许可证

36KB
1K SLoC

Transaction

一个零成本的交易抽象库。此 crate 提供了抽象和组合事务的方式。组合计算是在事务下运行的。不仅可以在事务下组合运行,它还 要求 计算是组合并在事务下运行的。

要运行事务,请使用类似 transaction-stmtransaction-diesel 的 crate


lib.rs:

Rust 中的零成本事务抽象

此 crate 抽象了类似 STM、SQL 事务等事务。它可以通过组合子进行组合,并执行事务的依赖注入。

基本思想是将“必须运行此计算”的契约表示为类型。trait Transaction 表示必须在事务下运行的计算序列。事务可以使用 thenand_thenor_else 等方式组合(序列化),因此可以像使用包装在 Result 中的值一样使用它。由于它表示在数据中运行的计算,因此提供了一些响应控制运算符的类型:用于 ?abort,用于 forrepeat,用于 looploop_fn,用于 (join point of) ifbranch 等。由于所有组合子都有自己的结果类型,因此在执行时不会进行调度,因此它是零成本的。

另一个特点是它执行事务的依赖注入。对于数据库事务,这意味着它从上下文中注入数据库连接。

示例


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| {
        // ..
        # let _ = (id, cn);
        # unimplemented!()
    }).boxed()

}

fn update_user<'a>(id: i64, name: &'a str) -> BoxTx<'a, Option<()>> {
    with_ctx(move |cn: &mut FooConnection| {
        // ..
        # let _ = (id, cn, name);
        # unimplemented!()
    }).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()
}

依赖项