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.
更多信息:
- 从 mongo 控制台插入有问题的集合效果很好
- 从所有集合中读取效果很好
- 读取和写入同一个数据库中的其他集合效果很好
- 写入曾经有效的有问题的集合。
错误信息是:
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。问题依然存在。
LastError
是 deprecated in 0.11, replaced 的 WriteResult
。
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。
感谢所有关注此问题的人。
奇怪的问题:当我的 play 应用程序尝试 insert/update 某些 mongo 数据库集合中的记录时使用 reactivemongo,操作似乎失败并显示一条神秘消息,但是实际上,记录确实得到 inserted/updated.
更多信息:
- 从 mongo 控制台插入有问题的集合效果很好
- 从所有集合中读取效果很好
- 读取和写入同一个数据库中的其他集合效果很好
- 写入曾经有效的有问题的集合。
错误信息是:
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。问题依然存在。
LastError
是 deprecated in 0.11, replaced 的 WriteResult
。
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。
感谢所有关注此问题的人。