0

I am using an Reactive Mongo with Scala and Play-Framework. I need to hitmultiple queries for update the result and retrieve the updated result. But in reactive our all queries are work in different threads, some time i need to sync the queries. How this is possible using Reactive Mongo. Follwoing is my code:

def videoDetails(videoId: String) = Action.async{
logger.info("In videoDetails controller method");

var videoIds: List[JsObject] = CustomUtility.convertStringIdToJsonCriteria(List[String]{videoId});
var query = Json.obj("_id" -> Json.obj("$in" -> videoIds));
var cursor: Cursor[Video] = videosCollection.find(query).cursor[Video];
var future: Future[Option[Video]] = cursor.headOption;
var hitCount: Future[Int] = future.map { videos => {
  if(!videos.isEmpty){
    videos.get.hitCount.get
  }else {
    0;
  }
}}
hitCount.flatMap { count => {
  videosCollection.update(query, Json.obj("$set" -> Json.obj("hitCount" -> (count+1)))).map{ lastError =>
      logger.debug(s"Successfully updated with LastError: $lastError");
    }
  var cursor: Cursor[Video] = videosCollection.find(query).cursor[Video];
  var future: Future[Option[Video]] = cursor.headOption;
  future.map { option => {
   if(!option.isEmpty) Ok(Json.toJson(option.get)) else Ok(Json.toJson(""))
  }}
}}
}

In above code, firstly i am fetch the record hit count using query, and in future map, create the update query for update my hit count of records. After the record is updated, Need to fetch latest detail for docuemnt. But accortding to above code. In every hit to the controller, that data is not consist. Because some, if all threads run one after another then the resule is good other wise, result is not right, because all threads run asyn. How can we process all thread in sync?

In Reactie Mongo, for create DTO is also a problem, some time data comes but some times not.

UPDATE

From the answer by @cchantep i update my code as below:

def videoDetails(videoId: String) = Action.async{
logger.info("In videoDetails controller method");

var videoIds: List[JsObject] = CustomUtility.convertStringIdToJsonCriteria(List[String]{videoId});
var query = Json.obj("_id" -> Json.obj("$in" -> videoIds));
var cursor: Cursor[Video] = videosCollection.find(query).cursor[Video];
for{
  hitCount <- cursor.headOption
  _ <- Promise.successful(hitCount.map { video => {
        videosCollection.update(query, Json.obj("$set" -> Json.obj("hitCount" -> (video.hitCount.get+1)))).map{ lastError =>
            logger.debug(s"Successfully updated with LastError: $lastError");
          }
      }}).future
  resultVideo <- cursor.headOption
  result <- Promise.successful(resultVideo.map { video => {
              Ok(Json.toJson(video))
            }}).future
}yield result.getOrElse(NotFound)
}

But still the data is not sync. some time i return the chages in video object and some time not.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Harmeet Singh Taara
  • 6,483
  • 20
  • 73
  • 126
  • Why do you wrap each RM result with `Promise.successful(...).future`? RM results are already `Future[T]`. – cchantep Mar 31 '15 at 08:43

1 Answers1

1

You can sequence the Mongo operations using for-comprehension.

for {
  a <- colA.find(...)
  b <- colB.find(...)
  _ <- colB.update(..., ...)
  c <- colB.find(...)//find if update ok
} yield c
cchantep
  • 9,118
  • 3
  • 30
  • 41
  • hello @cchantep , the `for-comprehension` is possible in `reactive-mongo` ? – Harmeet Singh Taara Mar 26 '15 at 09:08
  • i am doing following code `for{ hitCount <- cursor.headOption _ <- Promise.successful(hitCount.map { video => { videosCollection.update(query, Json.obj("$set" -> Json.obj("hitCount" -> (video.hitCount.get+1)))).map{ lastError => logger.debug(s"Successfully updated with LastError: $lastError"); } }}).future resultVideo <- cursor.headOption result <- Promise.successful(resultVideo.map { video => { Ok(Json.toJson(video)) }}).future }yield result.getOrElse(NotFound)` but still data is not in sync. – Harmeet Singh Taara Mar 26 '15 at 09:54
  • With for comprehension the composed future is executed in the same thread. Do you use a replica set? A specific write concern? – cchantep Mar 26 '15 at 10:09
  • If futures are sequenced in a for-comprehension and write ops only on a single node, then the issue is unlikely to come from the driver usage itself. – cchantep Mar 31 '15 at 08:41