我在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。
对于我如何设计这种逻辑以及如何通过重新思考我的方法并稍微改进实现来解决这个问题,我也会感激不尽。
答案 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)
但是,虽然它运作良好,但我并不特别喜欢这个解决方案。
也许我的恐惧是没有道理的,但我真的想要一个更权威的答案,我应该如何解决这个问题。