In the following example, I am using:
- MongoDB (> 3.0 with WiredTiger engine)
- Play framework 2.3.8 in Scala
- The org.reactivemongo:play2-reactivemongo:0.11.0.play23-M3
First of all, suppose we have the following document in a MongoDB collection called for instance "urlColl":
{
"_id" : ObjectId("5593bebe89645672000deec4"),
"url" : "urlPath",
"content" : [
"a",
"ab",
"abc",
"abcd"
]}
In Play, it is possible to stream new documents to the client side as soon as they are inserted in the "urlColl" collection, with the following method in Play:
def feed = Action {
val cursor = collection
.find(BSONDocument(), BSONDocument("content" -> 1))
.options(QueryOpts().tailable.awaitData)
.cursor[List[Try[BSONValue]]](ReadPreference.nearest)
val dataProducer = cursor.enumerate(Int.MaxValue).map(_.toString)
Ok.chunked(dataProducer &> EventSource()).as("text/event-stream")
}
and the implicit reader:
implicit object ContentToList extends BSONDocumentReader[List[Try[BSONValue]]] {
def read(doc: BSONDocument): List[Try[BSONValue]] = {
doc.getAs[BSONArray]("content").get.stream.toList
}
}
Then, each time a new document with a "content" array is inserted, it is automatically sent to the client.
My question is quite simple:
Is it possible to stream to the client the new data injected in the "content" sub array?
Indeed, since there is no new document inserted (a new value is inserted in the array of the existing document), nothing is detected in the cursor and a fortiori nothing is sent to the client.
Thank you in advance!
@cchantep, to answer your last comment:
Yes, I am facing some slow queries. In fact, I have one form in a web page used to push data, and another web page where the server sends the events.
Validating the form of the first page can take up to 3 seconds. In the Mongo logs, I can see:
I QUERY [conn329] getmore test.events cursorid:22982535122 ntoreturn:0
keyUpdates:0 writeConflicts:0 numYields:0 nreturned:1 reslen:86
locks:{ Global: { acquireCount: { r: 1000 } }, Database: { acquireCount:
{ r: 1000 } }, Collection: { acquireCount: { r: 1000 } } } 2783ms.
This is a log of the events collection (2783ms) due to the tailable cursor. Maybe this can cause the problem?
Edit: I have disabled the tailable cursor (coll.find(selector).options(QueryOpts().tailable.awaitData)) and the performances are far better. Do you have any idea?
Thank you!