#组合 #异步 #组合 #同步 # #函数 #返回

nightly function-compose

允许组合同步和异步 Rust 函数的库

4 个版本

新版本 0.2.0 2024 年 8 月 22 日
0.1.2 2024 年 6 月 27 日
0.1.1 2024 年 6 月 27 日
0.1.0 2024 年 6 月 27 日

701Rust 模式

MIT 许可证

28KB
307

function-compose

function-compose 是一个函数组合库,允许组合异步和同步函数

fn-composer 函数组合需要两个宏。

过程属性宏 - 可组合

声明性宏 - 组合!

过程属性宏可组合添加到任何可以组合的函数上。例如以下是一个简单的将 10 加到给定数字上的函数。

可组合宏文档

#[composeable()]
pub fn add_10(a: i32) -> Result<i32, String> {
    Ok(a + 10)
}

以下是一个异步示例。异步函数应返回 BoxFuture。

#[composeable()]
pub fn add_async(a: i32, b: i32) -> BoxFuture<'static, Result<i32, String>> {
    async move {
        let r = a + b;
        Ok(r)
    }.boxed()
}

以下是一个异步乘法和异步加 100 到一个数字的示例

#[composeable()]
pub fn multiply_async(a: i32, b: i32) -> BoxFuture<'static, Result<i32, String>> {
    async move {
        let r = a * b;
        Ok(r)
    }.boxed()
}

#[composeable()]
pub fn add_100_async(a: i32) -> BoxFuture<'static, Result<i32, String>> {
    async move {
        let r = a + 100;
        Ok(r)
    }.boxed()
}

以下是一个异步加 3 个值的示例

#[composeable()]
pub fn add_3_arg_async(a: i32,b: i32, c:i32) -> BoxFuture<'static, Result<i32, String>>{
    async move{
        let  r =   a + b + c;
        Ok(r)
    }.boxed()
}

以下是一个异步加 3 个值,最后一个参数接受引用的示例

#[composeable()]
pub fn add_3_arg_ref_async<'a>(a: i32,b: &'a i32, c:&'a i32) -> BoxFuture<'a, Result<i32, String>>{
    async move{
        let  r =   a + b + c;
        Ok(r)
    }.boxed()
}

可以将单个参数的同步函数与两个参数的异步函数组合,反之亦然。

以下是如何组合异步函数的示例

let result = compose!(add_10 -> add_100 -> with_args(10));
let result = compose!(add_10 -> add_100 -> add_10 -> add_100 -> with_args(10));

以下是如何组合异步和同步函数的示例

let result = compose!(add_100_async -> add_100 -> with_args(10)).await;
assert_eq!(210, result.unwrap());


let result = compose!(add_100_async -> add_100_async -> with_args(10)).await;
assert_eq!(210, result.unwrap());

可以使用 .provide 方法注入异步函数的第二个参数。这可以用于注入数据库连接或其他外部服务交互。请参阅以下示例

// Check the '.provide' method below of injecting second args to add_async function
let result = compose!(add_async.provide(100) -> add_100_async -> with_args(10)).await;
assert_eq!(210, result.unwrap());

多个注入到异步函数的示例

let result = compose!(add_3_arg_async.provide(100).provide(200) -> add_100_async -> with_args(10)).await;
assert_eq!(410, result.unwrap());

第二个位置注入到异步函数的示例


let result = compose!(add_100 -> add_3_arg_async.provide(1).provide(1) -> with_args(10)).await;
assert_eq!(112, result.unwrap());

共享引用到异步函数的多个注入示例

let one = &1;
let result = compose!(add_3_arg_ref_async.provide(one).provide(one) -> add_3_arg_async.provide(1).provide(1) -> with_args(10)).await;
assert_eq!(14, result.unwrap());

在 Fn Composer 中重试

可组合宏支持在函数返回错误时在指定间隔内重试函数。这在尝试进行数据库调用或连接到网络端点时可能很有用。在进行重试功能之前,请确保安装https://docs.rs/retry/latest/retry/

重试机制作为可组合过程宏的一部分实现。以下是一个配置为在初始失败后重试 2 次的 add_10 函数的示例。

use retry::delay::*;
#[composeable(retry = Fixed::from_millis(100).take(2))]
pub fn add_10(a: i32) -> Result<i32, String> {
    Ok(a + 10)
}

重试可以应用于同步和异步函数。

对于异步函数,函数的所有参数必须是共享引用或独占引用。

以下是带有重试功能的异步函数示例。

#[composeable(retry = Fixed::from_millis(100))]
pub fn add_3_arg_ref__non_copy_async<'a>(
    a: &'a mut Vec<String>,
    b: &'a mut Vec<String>,
    c: &'a Vec<String>,
) -> BoxFuture<'a, Result<i32, String>> {
    async move {
        let r = a.len() + b.len() + c.len();
        Ok(r as i32)
    }
    .boxed()
}

除了固定持续时间重试外,还可以配置指数延迟。有关所有可用的延迟选项,请参阅重试文档 https://docs.rs/retry/latest/retry/all.html

依赖项

~3–5MB
~84K SLoC