2 个不稳定版本
0.2.2 | 2023 年 1 月 23 日 |
---|---|
0.2.1 |
|
0.2.0 |
|
0.1.0 | 2023 年 1 月 21 日 |
1584 在 Rust 模式
25KB
395 行
context-rs
Go 一直建议你在异步上下文中的所有函数,如 Web 服务器,提供一个 ctx context.Context
参数。这对于将截止日期等信息传递到调用栈中很有用,以便允许叶函数安排关闭。
Rust 已经为所有异步函数自动传递了一个上下文值,这已经命名为 Context
,但它功能强大——只提供一个 '唤醒' 处理程序。
通过使用 nightly Provider API
,我们可以修改这个上下文,以在调用栈中按需提供值。这避免了使用 thread_locals,这需要 std
,或者在每个函数调用中传递一个 TypeMap
,这既不直观又需要 alloc
。
示例
使用 get_value
和 provide_ref
展示异步截止日期的示例
use context_rs::{get_value, ProviderFutExt};
use std::time::{Instant, Duration};
// New type makes it easier to have unique keys in the context
#[derive(Clone)]
struct Deadline(Instant);
#[derive(Debug, PartialEq)]
struct Expired;
impl Deadline {
// check if the deadline stored in the context has expired
// returns OK if no deadline is stored.
async fn expired() -> Result<(), Expired> {
get_value().await.map(|Deadline(deadline)| {
// if there is a deadline set, check if it has expired
if deadline < Instant::now() {
Err(Expired)
} else {
Ok(())
}
}).unwrap_or(Ok(())) // or ignore it if no deadline is set
}
}
// some top level work - agnostic to the context
async fn some_work() -> Result<(), Expired> {
loop {
some_nested_function().await?
}
}
// some deeply nested work, cares about the deadline context
async fn some_nested_function() -> Result<(), Expired> {
// will acquire the deadline from the context itself
Deadline::expired().await?;
// do some logic in here
Ok(())
}
#[tokio::main]
async fn main() {
// timeout in 2 seconds
let deadline = Instant::now() + Duration::from_secs(2);
let res = some_work().provide_ref(&Deadline(deadline)).await;
assert_eq!(res, Err(Expired));
}
如果你只需要临时访问值,并且你想要的值很昂贵,你可以使用 with_ref
而不是 get_value
。这将接受一个闭包,该闭包接受提供的引用,具有短暂的生存期。
依赖关系
~0–1.2MB
~20K SLoC