我将旧的Casbah Mongo驱动程序迁移到新的异步Scala驱动程序,我试图在Akka流中使用它,并且流卡住了。
我有一个定义了createLogic()的GraphStage。代码如下。这对Casbah来说很好用,我希望新mongo驱动程序的异步性能非常合适,但在这里会发生什么......
如果我通过此代码传输2条记录,则第一条记录会流过并触发下一步。请参阅下面的输出('此处发送'确认通过)。第二条记录似乎在BlacklistFilter中执行了正确的步骤,但Akka从未流向SEND步骤。
为什么不能使用新驱动程序的任何想法?
object BlacklistFilter {
type FilterShape = FanOutShape2[QM[RenderedExpression], QM[RenderedExpression], QM[Unit]]
}
import BlacklistFilter._
case class BlacklistFilter(facilities: Facilities, helloConfig: HelloConfig)(implicit asys: ActorSystem) extends GraphStage[FilterShape] {
val outPass: Outlet[QM[RenderedExpression]] = Outlet("Pass")
val outFail: Outlet[QM[Unit]] = Outlet("Fail")
val reIn: Inlet[QM[RenderedExpression]] = Inlet("Command")
override val shape: FilterShape = new FanOutShape2(reIn, outPass, outFail)
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
override def preStart(): Unit = pull(reIn)
setHandler(reIn, new InHandler {
override def onPush(): Unit = {
val cmd = grab(reIn)
val re: RenderedExpression = cmd.body
val check = re.recipient.contacts(re.media).toString
// NEW NON-BLOCKING CODE
//-------------------------------------
facilities.withMongo(helloConfig.msgDB, helloConfig.blacklistColl) { coll =>
var found: Option[Document] = None
coll.find(Document("_id" -> check)).first().subscribe(
(doc: Document) => {
found = Some(doc)
println("BLACKLIST FAIL! " + check)
emit(outFail, cmd)
// no pull() here as this happens on complete below
},
(e: Throwable) => {
// Log something here!
emit(outFail, cmd)
pull(reIn)
},
() => {
if (found.isEmpty) {
println("BLACKLIST OK. " + check)
emit(outPass, cmd)
}
pull(reIn)
println("Pulled reIn...")
}
)
}
// OLD BLOCKING CASBAH CODE THAT WORKED
//-------------------------------------
// await(facilities.mongoAccess().mongo(helloConfig.msgDB, helloConfig.blacklistColl)(_.findOne(MongoDBObject("_id" -> check)))) match {
// case Some(_) => emit(outFail, cmd)
// case None => emit(outPass, cmd)
// }
// pull(reIn)
}
override def onUpstreamFinish(): Unit = {} // necessary for some reason!
})
setHandler(outPass, eagerTerminateOutput)
setHandler(outFail, eagerTerminateOutput)
}
}
输出:
BLACKLIST OK. jsmith@yahoo.com
Pulled reIn...
HERE IN SEND (TemplateRenderedExpression)!!!
ACK!
BLACKLIST OK. 919-919-9119
Pulled reIn...
您可以从输出中看到第一条记录很好地流向了SEND / ACK步骤。第二条记录打印出BLACKLIST消息,意味着它发出outPass然后调用了reIn ...但是后来没有任何事情发生。
任何人都知道为什么这种方法在Akka Streams中的工作方式与Casbah版本的工作方式不同(代码显示已注释掉)?
(我可以将Mongo调用转换为Future并等待它,这应该像旧代码一样工作,但这有点打败了异步的全部意义!)
答案 0 :(得分:1)
那么......"没关系"! : - )
上面的代码似乎就像应该有效一样。然后我注意到Akka的家伙刚刚发布了新版本(2.0.1)。我不确定是什么调整,但不管它是什么,上面的代码现在可以起作用,因为我希望不需要修改。
留下这篇文章以防万一有人遇到类似的问题。