Play + ReactiveMongo:上限集合和tailable光标

时间:2015-05-18 23:33:55

标签: mongodb scala playframework reactivemongo capped-collections

我在Scala,Akka和ReactiveMongo上使用Play Framework。我想在MongoDB中使用一个集合作为循环队列。几个演员可以在其中插入文档;一个actor一旦可用就会检索这些文件(一种发布 - 订阅系统)。 我使用上限集合和tailable游标。每次我检索一些文件时,我必须运行命令EmptyCapped来刷新上限集合(它不可能从中删除元素)否则我总是检索相同的文档。有替代解决方案吗?例如,有没有一种方法可以滑动光标而不删除元素?或者最好不要在我的情况下使用上限收藏?

object MexDB {

def db: reactivemongo.api.DB = ReactiveMongoPlugin.db
val size: Int = 10000

// creating capped collection
val collection: JSONCollection = {

    val c = db.collection[JSONCollection]("messages")

    val isCapped = coll.convertToCapped(size, None)

    Await.ready(isCapped, Duration.Inf)

    c
}

def insert(mex: Mex) = {

    val inserted = collection.insert(mex)

    inserted onComplete {
      case Failure(e) =>
        Logger.info("Error while inserting task: " + e.getMessage())
        throw e

      case Success(i) =>
        Logger.info("Successfully inserted task")
    }

}


def find(): Enumerator[Mex] = {

  val cursor: Cursor[Mex] = collection
    .find(Json.obj())
    .options(QueryOpts().tailable.awaitData)
    .cursor[Mex]

    // meaning of maxDocs ???
    val maxDocs = 1
    cursor.enumerate(maxDocs)
}


def removeAll() = {
    db.command(new EmptyCapped("messages"))
}

}

/*** part of receiver actor code ***/

// inside preStart
val it = Iteratee.fold[Mex, List[Mex]](Nil) {
    (partialList, mex) => partialList ::: List(mex)
}

// Inside "receive" method
case Data =>

  val e: Enumerator[Mex] = MexDB.find()

  val future = e.run(it)

  future onComplete {
    case Success(list) =>
      list foreach { mex =>
        Logger.info("Mex: " + mex.id)
      }
      MexDB.removeAll()
      self ! Data

    case Failure(e) => Logger.info("Error:  "+ e.getMessage())
  }

1 个答案:

答案 0 :(得分:0)

在每个找到的文档maxDocs = 1后,您的tailable游标将关闭。为了无限期地保持开放,你应该省略这个限制。

使用awaitData时,只有在明确关闭RM时才会调用.onComplete

您需要使用光标中的某些流功能,例如.enumerate并处理每个新步骤/结果。见https://github.com/sgodbillon/reactivemongo-tailablecursor-demo/