Actix-web: отправить сообщение обработчику базы данных, условно отправить сообщение второму обработчику - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь отправить сообщение одному обработчику дБ и на основании результата отправить сообщение второму обработчику или вернуть ошибку первого.

То, что я до сих пор придумал, не работает; RustC говорит match arms have incompatible types

expected struct 'futures::future::and_then::AndThen', found enum 'std::result::Result'

state
    .db
    .send(...)
    .from_err()
    .and_then(|res| match res {
        Ok(response) => {
        // Do some additional logic here
        state
        .db
        .send(...)
        .from_err()
        .and_then(|res| match res {
            Ok(response) => Ok(HttpResponse::Ok().json(response)),
            Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
            }) 
        },
        Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
    })
    .responder()

Вопрос как это сделать в actix-web?

1 Ответ

0 голосов
/ 13 января 2019

Вы были почти там.

При использовании match все руки должны иметь одинаковый тип. В вашем случае одно - это будущее в сочетании с and_then, на другом - у вас есть result.

Кроме того, если ваша функция send() не возвращает тип impl Future<Item = Result<R, E>, Error = E>, match является полностью лишним. and_then принимает в качестве параметра Item, а не Result<Item, Error>.

Итак, все это можно просто уменьшить до:

state
  .db
  .send(...)
  .from_err()
  .and_then(|res| state.db.send(...).from_err())
  .then(|res| match res {
     Ok(response) => Ok(HttpResponse::Ok().json(response)),
     Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
   })
   .responder()

Давайте предположим, что ваши типы верны. Вы можете легко преобразовать это Result в future с помощью future::result следующим образом:

state
    .db
    .send(...)
    .from_err()
    .and_then(|res| future::result(res).from_err())
    .and_then(|res| 
        // Do some additional logic here
          state
          .db
          .send(...)
          .from_err()
     )
     .and_then(|res| future::result(res).from_err())
     .then(|res| match res {
       Ok(response) => Ok(HttpResponse::Ok().json(response)),
       Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
      })
     .responder()

Пример находится там в песочнице: https://play.rust -lang.org /? Version = stable & mode = debug & edition = 2018 & gist = 6801886b02081160e268f395bcc1ad6c

...