在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
?
答案 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)
}