rust - 我可以将值借入闭包而不是移动它们吗?
问题描述
我正在为用actix-web编写的服务器应用程序编写 GET 方法。LMDB是我使用的数据库,它的事务需要在其生命周期结束之前中止或提交。
为了避免一堆嵌套match
,我尝试map_err
在所有返回结果的函数上使用。在那里我尝试中止交易,但交易被移入关闭而不是被借用。
有什么办法可以将交易借入闭包中,还是我必须硬着头皮写一堆嵌套匹配?本质上,编写此函数的最符合人体工程学的方式是什么?
示例代码(参见旁边的注释txn.abort()
):
pub async fn get_user(db: Data<Database>, id: Identity) -> Result<Json<User>, Error> {
let username = id.identity().ok_or_else(|| error::ErrorUnauthorized(""))?;
let txn = db
.env
.begin_ro_txn()
.map_err(|_| error::ErrorInternalServerError(""))?;
let user_bytes = txn.get(db.handle_users, &username).map_err(|e| {
txn.abort(); // txn gets moved here
match e {
lmdb::Error::NotFound => {
id.forget();
error::ErrorUnauthorized("")
}
_ => error::ErrorInternalServerError(""),
}
})?;
let user: User = serde_cbor::from_slice(user_bytes).map_err(|_| {
txn.abort(); // cannot use txn here as is was moved
error::ErrorInternalServerError("")
})?;
txn.abort(); // cannot use txn here as is was moved
Ok(Json(user))
}
解决方案
可悲的是,在我的情况下,不可能将值借入关闭,因为abort
消耗了交易。(感谢@vkurchatkin 的解释)
如果有人感兴趣,我已经制定了一个无论问题如何都能让我满意的解决方案。我可以避免嵌套一堆match
es。
我将处理事务的所有逻辑移到一个单独的函数中,然后将函数的评估延迟Result
到运行之后txn.abort()
(见评论):
pub async fn get_user(db: Data<Database>, id: Identity) -> Result<Json<User>, Error> {
let username = id.identity().ok_or_else(|| error::ErrorUnauthorized(""))?;
let txn = db
.env
.begin_ro_txn()
.map_err(|_| error::ErrorInternalServerError(""))?;
let user = db_get_user(&db, &txn, &id, &username); // Execute separate function but do not evaluate the function Result yet, notice missing question mark operator!
txn.abort(); // Abort the transaction after running the code. (Doesn't matter if it was successful or not. This consumes the transaction and it cannot be used anymore.)
Ok(Json(user?)) // Now evaluate the Result using the question mark operator.
}
// New separate function that uses the transaction.
fn db_get_user(
db: &Database,
txn: &RoTransaction,
id: &Identity,
username: &str,
) -> Result<User, Error> {
let user_bytes = txn.get(db.handle_users, &username).map_err(|e| match e {
lmdb::Error::NotFound => {
id.forget();
error::ErrorUnauthorized("")
}
_ => error::ErrorInternalServerError(""),
})?;
serde_cbor::from_slice(user_bytes).map_err(|_| error::ErrorInternalServerError(""))
}
推荐阅读
- php - Bootstrap 4轮播下一张和上一张幻灯片不起作用
- javascript - http-proxy-middleware 提升:ERR_CONTENT_LENGTH_MISMATCH
- java - 如何将对象传递到新形式?
- sass - gulp-sass 不产生任何输出
- java - 为什么 Java Collector.toList() 在其返回类型中需要通配符类型占位符?
- javascript - 如何在handsontable的上下文菜单中添加带有默认项目的自定义项目
- python - 在定时嵌套循环中等待用户输入
- php - 防止 PHP 中的文件包含漏洞
- arrays - 如何在 Scala 中编写具有自定义索引范围的有效类数组结构?
- graph-databases - TTL 过期后,JanusGraph 边缘未删除