ReactiveMongo/Play: `LastError: DatabaseException['<none>']`, while db still updates

ReactiveMongo/Play: `LastError: DatabaseException['<none>']`, while db still updates

奇怪的问题:当我的 play 应用程序尝试 insert/update 某些 mongo 数据库集合中的记录时使用 reactivemongo,操作似乎失败并显示一条神秘消息,但是实际上,记录确实得到 inserted/updated.

更多信息:

  1. 从 mongo 控制台插入有问题的集合效果很好
  2. 从所有集合中读取效果很好
  3. 读取和写入同一个数据库中的其他集合效果很好
  4. 写入曾经有效的有问题的集合。

错误信息是:

play.api.http.HttpErrorHandlerExceptions$$anon: Execution exception[[LastError: DatabaseException['<none>']]]
  at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
  at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
  at play.core.server.netty.PlayRequestHandler$$anonfun$$anonfun$apply.applyOrElse(PlayRequestHandler.scala:100)
  at play.core.server.netty.PlayRequestHandler$$anonfun$$anonfun$apply.applyOrElse(PlayRequestHandler.scala:99)
  at scala.concurrent.Future$$anonfun$recoverWith.apply(Future.scala:344)
  at scala.concurrent.Future$$anonfun$recoverWith.apply(Future.scala:343)
  at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
  at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
  at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
  at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
Caused by: reactivemongo.api.commands.LastError: DatabaseException['<none>']

使用 ReactiveMongo 0.11.14、Play 2.5.4、Scala 2.11.7、MongoDB 3.4.0.

谢谢!

更新 - 谜团加深了!

根据@Yaroslav_Derman的回答,我添加了一个.recover子句,如下所示:

collectionRef.flatMap( c =>
  c.update( BSONDocument("_id" -> publicationWithId.id.get), publicationWithId.asInstanceOf[PublicationItem], upsert=true))
  .map(wr => {
    Logger.warn("Write Result: " + wr )
    Logger.warn("wr.inError: " + wr.inError)
    Logger.warn("*************")
    publicationWithId
  }).recover({
  case de:DatabaseException => {
    Logger.warn("DatabaseException: " + de.getMessage())
    Logger.warn("Cause: " + de.getCause())
    Logger.warn("Code: " + de.code)
    publicationWithId
  }
})

确实调用了恢复子句。这是日志:

[info] application - Saving pub t3
[warn] application - *************
[warn] application - Saving publication     Publication(Some(BSONObjectID("5848101d7263468d01ff390d")),t3,2016-12-07,desc,auth,filename,None)
[info] application - Resolving database...
[info] application - Resolving database...
[warn] application - DatabaseException: DatabaseException['<none>']
[warn] application - Cause: null
[warn] application - Code: None

所以没有原因,没有代码,消息是“'<none>'”,但仍然是一个错误。给出了什么?

我尝试移动到 0.12,但这导致整个应用程序出现一些编译错误,而且我不确定这是否能解决问题。所以我想先搞清楚是怎么回事。

更新#2: 迁移到 reactive-mongo 0.12.0。问题依然存在。

LastErrordeprecated in 0.11, replacedWriteResult

LastError实际上并不意味着错误,它可能意味着成功的结果,LastError对象的you need to checkinError属性检测是否这是真正的错误。如我所见,'<none>' 错误消息很可能表明这不是错误。

示例如下 "how it was in 0.10":http://reactivemongo.org/releases/0.10/documentation/tutorial/write-documents.html

玩reactivemongo 0.12.0你可以这样做

def appsDb = reactiveMongoApi.database.map(_.collection[JSONCollection](DesktopApp.COLLECTION_NAME))

def save(id: String, user: User, body: JsValue) = {
    val version = (body \ "version").as[String]
    val app = DesktopApp(id, version, user)

    appsDb.flatMap(
      _.insert(app)
        .map(_ => app)
        .recover(processError)
    )
  }

def processError[T]: PartialFunction[Throwable, T] = {
    case ex: DatabaseException if ex.code.contains(10054 | 10056 | 10058 | 10107 | 13435 | 13436) =>
      //Custom exception which processed in Error Handler
      throw new AppException(ResponseCode.ALREADY_EXISTS, "Entity already exists")

    case ex: DatabaseException if ex.code.contains(10057 | 15845 | 16550) =>
      //Custom exception which processed in Error Handler
      throw new AppException(ResponseCode.ENTITY_NOT_FOUND, "Entity not found")

    case ex: Exception =>
      //Custom exception which processed in Error Handler
      throw new InternalServerErrorException(ex.getMessage)
  }

您也可以在processError方法

中添加日志

通过降级到 MongoDB 3.2.8 解决了问题。原来 reactiveMongo 0.12.0 是 not compatible with mongoDB 3.4

感谢所有关注此问题的人。