как вернуть либо значение, либо ошибку в Scala - PullRequest
0 голосов
/ 07 марта 2019

У меня есть список электронных писем, для каждого из которых я посмотрю его в таблице электронной почты, чтобы увидеть, существует ли это письмо. если это произойдет, больше ничего не сделаю, я выдам ошибку. вот мой код;

def lookupEmailStatus(email: EmailAddress, requestId: RequestId)(
      implicit ec: ExecutionContext): HttpServiceResult[List[EmailStatusDTO]] = {
    emailDatabase
      .getEmailStatusByEmail(email, requestId)
      .map(
        l =>
        if (l.isEmpty) {
          logger.error(
            LoggingMessage(
              requestId,
              s"Email status not found by ${email.email} failed"))
          EntityNotFound(s"${email.email}", requestId)
        } else {
          l
        }
      )
      .leftMap[HttpError] {
        case e =>
          logger.error(
            LoggingMessage(
              requestId,
              s"Retrieve email status by ${email.email} failed"))
          DatabaseError(e.message, requestId)
      }
  }

когда я запускал код получил ошибку:

Error:(57, 27) type mismatch;
 found   : cats.data.EitherT[model.HttpError,Product with Serializable]
 required: model.HttpServiceResult[List[EmailStatusDTO]]
    (which expands to)  cats.data.EitherT[model.HttpError,List[EmailStatusDTO]]
      .leftMap[HttpError] {

если я уберу метод .map (..), он будет работать нормально, но это не то, что я хочу:

def lookupEmailStatus(email: EmailAddress, requestId: RequestId)(
          implicit ec: ExecutionContext): HttpServiceResult[List[EmailStatusDTO]] = {
        emailDatabase
          .getEmailStatusByEmail(email, requestId)
          .leftMap[HttpError] {
            case e =>
              logger.error(
                LoggingMessage(
                  requestId,
                  s"Retrieve email status by ${email.email} failed"))
              DatabaseError(e.message, requestId)
          }
      }

вот определения типов:

type HttpServiceResult[A] = ServiceResult[HttpError, A]
type ServiceResult[Err, A] = EitherT[Future, Err, A]

Ответы [ 2 ]

4 голосов
/ 07 марта 2019

Если одна ветвь if возвращает список, а другая возвращает ошибку, то полностью if возвращает Product with Serializable.

Попробуйте заменить map на flatMap и обернуть результаты ветвейс EitherT

def lookupEmailStatus(email: EmailAddress, requestId: RequestId)(
    implicit ec: ExecutionContext): HttpServiceResult[List[EmailStatusDTO]] = 
    emailDatabase
      .getEmailStatusByEmail(email, requestId)
      .leftMap[HttpError] {
        case e =>
          logger.error(
            LoggingMessage(
              requestId,
              s"Retrieve email status by ${email.email} failed"))
          DatabaseError(e.message, requestId)
      }.flatMap[HttpError, List[EmailStatusDTO]](
        /*(*/l/*: List[EmailStatusDTO])*/ =>
          if (l.isEmpty) {
            logger.error(
              LoggingMessage(
                requestId,
                s"Email status not found by ${email.email} failed"))
            EitherT.leftT/*[Future, List[EmailStatusDTO]]*/(EntityNotFound(s"${email.email}", requestId))
          } else {
            EitherT.rightT/*[Future, HttpError]*/(l)
          }
      )
1 голос
/ 07 марта 2019

Как уже упоминалось @ dmytro-mitin, основная причина вашей проблемы заключается в том, что вы не возвращаете один и тот же тип в обеих ветвях условного выражения.Один из способов исправить это - убедиться, что вы возвращаете правильный тип.

Другой и, на мой взгляд, лучший способ - использовать cats.data.EitherT.ensure для проверки list.isEmpty.Таким образом, вы четко определяете, что вас волнует (например, если список пуст, возвращает ошибку), и вам не нужно вручную разбираться со счастливым случаем.

Ваш код станет:

def lookupEmailStatus(email: EmailAddress, requestId: RequestId)(
      implicit ec: ExecutionContext): HttpServiceResult[List[EmailStatusDTO]] = {
    emailDatabase
      .getEmailStatusByEmail(email, requestId)
      .ensure({
         logger.error(LoggingMessage(requestId, s"Email status not found by ${email.email} failed"))}
         EntityNotFound(s"${email.email}", requestId)
      })(!_.isEmpty)
      .leftMap[HttpError] {
        case e =>
          logger.error(
            LoggingMessage(
              requestId,
              s"Retrieve email status by ${email.email} failed"))
          DatabaseError(e.message, requestId)
      }
  }
...