具有2进2出形状的GraphStage

时间:2019-05-09 20:11:53

标签: scala akka akka-stream

我需要编写一个具有两个输入端口和两个输出端口的自定义GraphStage。该GraphStage将允许两个原本独立的流互相影响。我可以使用什么形状? FanOutShape2有两个输出,而FanInShape2有两个输入,但是我如何拥有同时具有这两个形状的形状?以某种方式将两者结合(继承)?使用BidiFlow?做我自己的吗?

1 个答案:

答案 0 :(得分:0)

我自己回答,因为这已经由forum.lightbend.com上的有用人员解决了,请参见https://discuss.lightbend.com/t/graphstage-with-shape-of-2-in-and-2-out/4160/3

这个问题的答案是简单地使用BidiShape。尽管具有其他名称,但BidiShape背后的逻辑绝不是双向的(回想起来很明显,但我对此不予理))。

如果有人处于相似的情况下,某些代码可以用作参考,他们必须基于两个输入来做某事,并且有可能推送到两个输出:

class BiNoneCounter[T]() extends GraphStage[BidiShape[Option[T], Option[Int], Option[T], Option[Int]]] {
  private val leftIn = Inlet[Option[T]]("BiNoneCounter.in1")
  private val rightIn = Inlet[Option[T]]("BiNoneCounter.in2")
  private val leftOut = Outlet[Option[Int]]("BiNoneCounter.out1")
  private val rightOut = Outlet[Option[Int]]("BiNoneCounter.out2")
  override val shape = BidiShape(leftIn, leftOut, rightIn, rightOut)

  override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
    private var grabNextPush = false

    val inHandler = new InHandler {
      override def onPush(): Unit = {
        if (grabNextPush) {
          (grab(leftIn), grab(rightIn)) match {
            // do stuff here
          }
        }
        grabNextPush = !grabNextPush
      }
    }

    val outHandler = (inlet: Inlet[Option[T]]) => new OutHandler {
      override def onPull(): Unit = {
        pull(inlet)
      }
    }

    setHandler(leftOut, outHandler(leftIn))
    setHandler(rightOut, outHandler(rightIn))
    setHandler(leftIn, inHandler)
    setHandler(rightIn, inHandler)
  }
}

可以这样使用:

        sourceOne ~> bidi.in1
                     bidi.out1 ~> sinkOne
        sourceTwo ~> bidi.in2
                     bidi.out2 ~> sinkTwo