0

This is my first attempt at writing a small webservice with rust, using actix-web.

The code below is a request handler that is intended to do three things, insert an entry in the database, send an email if that db call was successful, and then return a json payload as the response.

data.dal (database call) and data.email_service are references to Actors.

The issue: is I am unable to capture the error returned by data.dal. Any attempt to reconfigure the below code seems to give me an error stating the compiler wasn't able to find a conversion from Actix Mailbox to [Type].

Is there an alternate/better way to rewrite this? Basically when the request is issued, I'd like to be able to call Actor A. And if the result from A is Ok then call Actor B. If the results from both are okay return a JSON payload. If either A or B return an error (can have different error types), return an custom error message.

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())
                    }
                })
        })
}
4

1 回答 1

0

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

我还没有测试过这个代码片段,但这就是我在使用 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那样)

于 2019-09-09T06:09:00.610 回答