使用statefulMapConcat返回源代码

时间:2017-09-09 14:48:59

标签: scala akka-stream

在akka-http websocket应用程序中,我有一个回显给定消息的Route,我还需要在应用程序中维护状态。所以以下工作正常:

  override protected def routes: Route =
    pathSuffix("echo") {
      handleWebSocketMessages(echoMessageFlow)
    }

  def echoMessageFlow: Flow[Message, Message, NotUsed] = Flow[Message].statefulMapConcat { () =>
    implicit var state = new SessionState()
    msg: Message =>
    List(msg, msg, msg) // echo the message back 3 times
  }

但是,我还需要限制回显消息,因此每秒只发生一次。所以我希望能够做到这一点:

  def echoMessageFlow: Flow[Message, Message, NotUsed] = Flow[Message].statefulMapConcat { () =>
    implicit var state = new SessionState()
    msg: Message =>
    Source(List(msg, msg, msg)).throttle(1, 1 second, 1, ThrottleMode.shaping) 
  }

但是,statefulMapConcat返回的函数要求它是Iterable。有没有办法返回Source

1 个答案:

答案 0 :(得分:1)

您可以使用flatMapConcat(或flatMapMerge,如果您需要并行化)并为其提供一个为每个传入元素生成Source的函数。

每个生成的Source都可以通过附加throttle组合子来加以限制,就像你上面那样。

最后,如果您希望Source有状态,可以使用Source.unfold创建。

下面的示例(使用生成的消息计数作为内部状态):

  def echoMessageFlow: Flow[Message, Message, NotUsed] = Flow[Message].flatMapConcat { msg: Message => 
    Source.unfold(0){ count: Int ⇒ 
      if (count < 3)
        Some(count + 1, msg)
      else
        None
    }.throttle(1, 1.second, 1, ThrottleMode.shaping)
  }