在发送成功的JSON响应之前等待数据库事务结果

时间:2016-01-21 15:37:48

标签: mongodb scala playframework

我在db对象中有以下函数,它使用reactivemongo将文档写入mongoDB。

def writeDocument(json: JsValue):Future[WriteResult] = {

  def collection: JSONCollection = {
     val driver = new MongoDriver
     val connection = driver.connection(List("localhost"))
     val db = connection("superman")
     db.collection[JSONCollection]("Powers")
  }

val document = json.as[JsObject]
val future = collection.insert(document)
future.onComplete {
  case Failure(e) => {
    logger.error("""Message="Database is not reachable." """ + """ transactionID=""" + (json \\ "transactionID") + " errorResponse=" + e.getLocalizedMessage)
    throw e}
  case Success(result) =>
    println("successfully inserted document with result = " + result)
}
future
 }

在控制器端,我有这部分代码调用上面的writeDocument()函数。由于reactivemongo是异步的,即使数据库不存在,我总是会获得成功的JSON消息。我知道数据库写入是通过Futures发生的,我如何确保只有在数据写入数据库成功后才发回成功的响应?

def validateRequest(json: JsValue): Result = {

{
  val logger = LoggerFactory.getLogger("superman")
  val jsonSchema = Source.fromURL(getClass.getResource("/schema.json")).getLines.mkString
  val transactionID = (json \ "transactionID").get
  val result: VA[JsValue] = SchemaValidator.validate(Json.fromJson[SchemaType](
    Json.parse(jsonSchema.stripMargin)).get, json)

  result.fold(
    invalid = { errors =>

      var violatesList = List[String]()
      val invalidError = Json.obj("transactionID" -> transactionID, "status" -> "error", "description" -> "Invalid Request Received")
      for (msg <- (errors.toJson \\ "msgs")) {
        violatesList = (msg(0).get).as[String] :: violatesList
      }
      val errorResponse = Json.toJson(invalidError ++ Json.obj("violations" -> violatesList))
      logger.error( """Message="Invalid Request Received" for transactionID=""" + transactionID.toString() + "errorResponse:" + errorResponse)
      BadRequest(errorResponse)

    },

    valid = {
      post =>
        val insertResult = db.writeDocument(json)
        insertResult.map{ result =>
          val json = Json.obj("transactionID" -> transactionID.toString,
            "status" -> "OK", "message" -> ("Valid Request Received"))
          Ok(json)
        }.recover{ case error: Throwable =>
          val json = Json.obj("transactionID" -> transactionID.toString,
            "status" -> "FAILED")
          Ok(json)
        }




  )
}

}

2 个答案:

答案 0 :(得分:1)

简单地转发未来并将其映射到想要的Result

一旦兑换承诺,Play就会提供此结果:Play Async

def writeDocument(json: JsValue): Future[LastError] = {
  // ...
  future
}


valid = { post =>
  val future = db.writeDocument(json)
  future.map { _ =>
    val successResponse = Json.obj("transactionID" -> transactionID.toString, "status" -> "OK", "message" -> ("Valid Request Received"))
    Ok(successResponse)
  }
}

答案 1 :(得分:1)

您需要进行以下更改:

1.在writeDocument结束而不是(或除了)直接处理未来之前,你应该回归未来。

2.在你的控制器中,你应该通过写下类似的东西将未来映射到答案:

def myAction() = Action.async { request =>
  insertResult.map{ result =>
    val json = Json.obj("transactionID" -> transactionID.toString,
                        "status" -> "OK", "message" -> ("Valid Request Received"))
    Ok(json)
  }.recover{ case error: Throwable =>
    val json = Json.obj("transactionID" -> transactionID.toString,
                        "status" -> "FAILED")
    Ok(json)
  }
}