使用ReactiveMongo处理从上限集合到中断的作业

时间:2015-01-13 13:02:47

标签: mongodb scala reactivemongo iterate capped-collections

我在MongoDB中有一个jobs_queue集合。它是一个上限集合,我使用一个可用的游标进行轮询:

val cur =
  jobsQueue
    .find(Json.obj("done" -> Json.obj("$ne" -> true)))
    .options(QueryOpts().tailable.awaitData)
    .cursor[JsObject]

cur.enumerate() |>>> Iteratee.foreach { queuedDoc =>
  // do some processing and store the results back in the DB
}

这是从常规Scala App调用的,因此根本没有Akka或Play包装。

在明确突破App之前,确保Iteratee.foreach不退出的最合适方法是什么?此外,如果有更简单(即使稍微不那么优雅)的方式,我也不必使用play-iteratees 。


P.S。 我确保收集上限:

val jobsQueueMaybe = db.collection[JSONCollection]("jobs_queue")
val jobsQueue: JSONCollection =
  jobsQueueMaybe.stats()
    .flatMap {
      case stats if !stats.capped =>
        jobsQueueMaybe.convertToCapped(size = 1024 * 1024, maxDocuments = None)
      case _ =>
        Future(jobsQueueMaybe)
    }
    .recover { case _ => jobsQueueMaybe.createCapped(size = 1024 * 1024, maxDocuments = None) }
    .map { _ => jobsQueueMaybe }

P.P.S。

对于我如何设计这种逻辑以及如何通过重新思考我的方法并稍微改进实现来解决这个问题,我也会感激不尽。

1 个答案:

答案 0 :(得分:1)

作为当前的解决方法,我从Iteratee.foreach更改为Iteratee.foldM,以便每次迭代都返回Future;通过这种方式,它似乎迫使ReactiveMongo继续计算直到被中断,而不是foreach似乎过早退出:

cur.enumerate() |>>> Iteratee.foldM(()) { (acc, queuedDoc) =>
  // always yield something like Future.successful(acc) or an actual `Future[Unit]`
}

然后,我只需要等到整个程序终止(通过将某些内容放入stopSignal: ConcurrentLinkedQueue发出信号:

while (stopSignal.isEmpty) Thread.sleep(1000)

但是,虽然它运作良好,但我并不特别喜欢这个解决方案。

也许我的恐惧是没有道理的,但我真的想要一个更权威的答案,我应该如何解决这个问题。