【问题标题】:Error handling and conditional chaining of Actix actorsActix Actor 的错误处理和条件链接
【发布时间】:2019-09-09 14:09:00
【问题描述】:

这是我第一次尝试使用 actix-web 编写一个带有 rust 的小型 web 服务。

下面的代码是一个请求处理程序,它打算做三件事,在数据库中插入一个条目,如果该 db 调用成功则发送电子邮件,然后返回一个 json 有效负载作为响应。

data.dal(数据库调用)和data.email_service是对Actor的引用。

问题:我无法捕获data.dal 返回的错误。任何重新配置​​以下代码的尝试似乎都会给我一个错误,指出编译器无法找到从 Actix Mailbox 到 [Type] 的转换。

是否有替代/更好的方法来重写它?基本上,当发出请求时,我希望能够调用 Actor A。如果 A 的结果正常,则调用 Actor B。如果两者的结果都正常,则返回 JSON 有效负载。如果 A 或 B 返回错误(可以有不同的错误类型),则返回自定义错误消息。

pub fn register_email(
    invitation: Json<EmailInvitationInput>,
    data: web::Data<AppState>,
) -> impl Future<Item=HttpResponse, Error=Error> {
    let m = dal::queries::CreateEmailInvitation { email: invitation.email.clone() };
    data.dal.send(m)
        .from_err()
        .and_then(move |res| {
            let invite = res.unwrap();
            let email_input = email::SendLoginLink {
                from: "from_email".to_string(),
                to: "to_email".to_string(),
            };
            data.email_service.send(email_input)
                .from_err()
                .and_then(move |res| match res {
                    Ok(_) => {
                        Ok(HttpResponse::Ok().json(EmailInvitationOutput { expires_at: invite.expires_at }))
                    }
                    Err(err) => {
                        debug!("{:#?}", err);
                        Ok(ServiceError::InternalServerError.error_response())
                    }
                })
        })
}

【问题讨论】:

    标签: rust rust-actix actix-web


    【解决方案1】:

    我通常做的是拥有一个聚合所有不同错误的Error 类型,可以通过声明适当的From 实现和你在做什么from_err() 来隐式地实现对这种类型的强制,但我在这里明确:

    我还没有测试过这个代码 sn-p 但这就是我在使用 Actix 的项目中所做的:

    data.dal.send(m)
        .map_err(Error::Mailbox)
        .and_then(|res| res.map_err(Error::Service))
        .and_then(move |invite| {
            let email_input = email::SendLoginLink {
                from: "from_email".to_string(),
                to: "to_email".to_string(),
            };
            data.email_service.send(email_input)
                .map_err(Error::Mailbox)
                .and_then(|res| res.map_err(Error::Service))
                .and_then(move |res| HttpResponse::Ok().json(EmailInvitationOutput { expires_at: invite.expires_at }))
        })
        .or_else(|err| {
            debug!("{:#?}", err);
            ServiceError::InternalServerError.error_response()
        })
    

    (我假设 ServiceError 实现 IntoFuture 就像 HttpResponse 一样)

    【讨论】:

      猜你喜欢
      • 2014-05-31
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 2020-06-30
      • 2020-06-27
      相关资源
      最近更新 更多