将成功转换为失败的最佳方式取决于成功的值

时间:2017-02-09 09:53:18

标签: scala playframework playframework-2.3 reactivemongo play-reactivemongo

我用Play!使用ReactiveMongo插件的框架(相应版本2.3和0.11)。我有下一个代码从MongoDB集合中删除项目并返回一些受影响的项目:

/**
  * Removes all subscribers by subscription id
  * 
  * @param subscriptionId id of the subscription
  * @return count of removed subscribers
  */  
def deleteAll(subscriptionId: String): Future[Int] = {
      logger.debug(s"Removing all subscribers with subscription id '$subscriptionId'...")
      val query = BSONDocument("subscriptionId" -> BSONObjectID(subscriptionId))
      subscribersCollection.remove(query) map { writeResult: WriteResult =>
        writeResult.n match {
          case subscribersRemoved if subscribersRemoved > 0 =>
            logger.debug(s"Successfully removed $subscribersRemoved subscribers with subscribtion id '$subscriptionId'")
          case _ => logger.debug(s"No subscribers with subscribtion id '$subscriptionId' were removed")
        }
        writeResult.n
      }
  }

由于ReactiveMongo文档,集合WriteResult方法返回的remove()类具有hasErrorwriteErrors等字段,用于指示执行期间发生的错误数据库查询。

那么,根据WriteResult的{​​{1}}字段,为了从中返回失败,最好和最干净的方法是什么?

这是一个粗略的例子:

hasError

即。即使数据库查询返回带有错误字段的subscribersCollection.remove(query).??? match { case Success(writeResult) if writeResult.hasErrors => Failure(new DatabaseException(writeResult.errMsg, writeResult.code) case any => any }

,我的方法也应返回Failure

提前致谢!我真的很感激任何帮助,以使我的代码更好

P.S。我已经考虑将所有代码包装在Success中,只是在设置为Try的{​​{1}}标记上抛出异常,但我相信它可以以更好的方式完成,也许可以{ {1}} hasError方法

P.P.S。出于某种原因,来自ReactiveMongo documentation的代码示例和演示不处理true的错误字段和标记。事实上,文档说

  

如果写入结果实际指示错误,则Future将进入   失败的状态

但是,我已经在几个应用程序中看到了生产代码中的这种处理,所以它有点令人困惑。这是否意味着这种处理过度?

1 个答案:

答案 0 :(得分:2)

使用flatMapFuture.failed

flatMap上执行Future,然后根据值Future.failed(new Exception("unexpected value"))

假设我们有一个返回某个int的未来的函数

def httpStatus: Future[Int] = Future { 404 }

httpStatus.flatMap { 
 case 404 => //return failed future
  Future.failed(new Exception("Bad status"))
 case value => value
}

现在您的代码变为

def deleteAll(subscriptionId: String): Future[Int] = {
      logger.debug(s"Removing all subscribers with subscription id '$subscriptionId'...")
      val query = BSONDocument("subscriptionId" -> BSONObjectID(subscriptionId))
      subscribersCollection.remove(query) flatMap { writeResult: WriteResult =>
        writeResult.n match {
          case subscribersRemoved if subscribersRemoved > 0 =>
            logger.debug(s"Successfully removed $subscribersRemoved subscribers with subscribtion id '$subscriptionId'")
            Future.successful(writeResult.n)
          case status => 
             logger.debug(s"No subscribers with subscribtion id '$subscriptionId' were removed")
             Future.failed(new Exception(s"bad status exception. status: $status"))
        }

      }
  }