如何在多个来源之间切换?

时间:2017-01-12 19:37:23

标签: scala akka akka-stream

假设我有两个相同类型的无限来源,可以连接到一个图表。我想从外部已经物化的图表之间切换,可能与使用KillSwitch关闭其中一个图标的方式相同。

val source1: Source[ByteString, NotUsed] = ???
val source2: Source[ByteString, NotUsed] = ???

val (switcher: Switcher, source: Source[ByteString, NotUsed]) = 
    Source.combine(source1,source2).withSwitcher.run()

switcher.switch()

默认情况下,我想使用source1,切换后我想使用source2

中的数据
source1 
        \
          switcher ~> source    

source2

是否可以使用Akka Streams实现此逻辑?

1 个答案:

答案 0 :(得分:2)

好的,过了一段时间我找到了解决方案。

所以在这里我可以使用与VLAN中相同的原理。我只需要标记我的源代码然后通过MergeHub传递它们。之后,很容易通过标记过滤这些来源并生成正确的结果作为来源。

我需要从一个源切换到另一个源是更改过滤条件。

source1.map(s => (tag1, s))
                           \
                             MergeHub.filter(_._1 == tagX).map(_._2) -> Source
                           /
source2.map(s => (tag2, s))

以下是一些例子:

object SomeSource {

  private var current = "tag1"

  val source1: Source[ByteString, NotUsed] = ???
  val source2: Source[ByteString, NotUsed] = ???

  def switch = {
     current = if (current == "tag1") "tag2" else "tag1"
  }

  val (sink: Sink[(String, ByteString), NotUsed], 
       source: Source[ByteString, NotUsed]) =
    MergeHub.source[(String, ByteString)]
      .filter(_._1 == current)
      .via(Flow[(String, ByteString)].map(_._2))
      .toMat(BroadcastHub.sink[ByteString])(Keep.both).run()

  source1.map(s => ("tag1", s)).runWith(sink)
  source2.map(s => ("tag2", s)).runWith(sink)

}

SomeSource.source    // do something with Source

SomeSource.switch()  // then switch