简体   繁体   English

如何将MongoDB Scala异步驱动程序与Akka Streams集成?

[英]How can I integrate MongoDB Scala Async driver with Akka Streams?

I'm migrating my old Casbah Mongo drivers to the new async Scala drivers and I'm trying to use this in an Akka stream, and the stream is getting stuck. 我正在将旧的Casbah Mongo驱动程序迁移到新的异步Scala驱动程序,并且试图在Akka流中使用它,并且该流卡住了。

I have a GraphStage with createLogic() defined. 我有一个带有createLogic()的GraphStage。 The code is below. 代码如下。 This worked fine with Casbah and I'd hoped the async nature of the new mongo drivers would be a great fit, but here what happens... 这在Casbah上很好用,我希望新的mongo驱动程序的异步特性非常合适,但是在这里发生了什么...

If I stream 2 records through this code, the first record flows through and triggers the next step. 如果我通过此代码流2条记录,则第一条记录将流过并触发下一步。 See output below ('HERE IN SEND' confirms it got through). 请参见下面的输出(“ HERE IN SEND”确认通过)。 The second record seems to go through the right steps in BlacklistFilter but Akka never flows to the SEND step. 第二条记录似乎在BlacklistFilter中经过正确的步骤,但Akka从未流向SEND步骤。

Any ideas why this is not working with the new drivers? 有什么想法为什么这不适用于新驱动程序?

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)
  }
}

Output: 输出:

BLACKLIST OK. jsmith@yahoo.com
Pulled reIn...
HERE IN SEND (TemplateRenderedExpression)!!!
ACK!
BLACKLIST OK. 919-919-9119
Pulled reIn...

You can see from the output that the first record flowed nicely to the SEND/ACK steps. 从输出中可以看到,第一个记录很好地流向了SEND / ACK步骤。 The second record printed the BLACKLIST message, meaning it emitted outPass then called pull on reIn... but then nothing happens downstream. 第二条记录打印了BLACKLIST消息,这意味着它发出了outPass,然后称为pull on reIn ...,但是随后没有任何反应。

Anyone know why this would work differently in Akka Streams than the Casbah version that worked fine (code shown commented out)? 任何人都知道为什么它在Akka Streams中的工作方式与工作正常的Casbah版本不同(显示的代码已注释掉)?

(I could just convert the Mongo call to a Future and Await on it, and that should work like the old code, but that kinda defeats the whole point of going async!) (我可以将Mongo调用转换为Future并在其上等待,这应该像旧代码一样工作,但这有点违反了进行异步操作的要点!)

Well then... "never mind"! 那么...“没关系”! :-) :-)

The code above seemed like it should work. 上面的代码似乎应该工作。 I then noticed the Akka guys have just released a new version (2.0.1). 然后我注意到Akka家伙刚刚发布了新版本(2.0.1)。 I'm not sure what tweaks lay within, but whatever it was, the code above now works as I'd hoped w/o modification. 我不确定要进行哪些调整,但是无论它是什么,上面的代码现在都可以按我希望的方式工作,而无需修改。

Left this post up just in case anyone hits a similar problem. 以防万一有人遇到类似问题,请保留此帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM