[英]Akka HTTP WebSocket Server How to declare Source based on Sink content when building Flow for message handlement?
I am playing around with Akka Stream/Http and trying to figure out how to do the following thing in a websocket server (hopefully without using Actor pattern):我正在玩 Akka Stream/Http 并试图弄清楚如何在 websocket 服务器中执行以下操作(希望不使用 Actor 模式):
1. At initial connection request from client, after the handshake, server will listen to client's initial Message
in json
format. 1.客户端初始连接请求,握手后,服务器会监听客户端的初始
Message
,格式为json
。
2. After server received the TextMessage.Strict
and if valid it will enrich the Message
to build a "Predicate" (eg. a filter map), Then the server will use that "Predicate" to build a Source[Message, _]
. 2. 服务器收到
TextMessage.Strict
后,如果有效,它将丰富Message
以构建“谓词”(例如过滤器映射),然后服务器将使用该“谓词”构建Source[Message, _]
。
I tried using handleMessagesWithSinkSource
but it seems to me this API's intend is for out-generating Sink
and Source
independently(see route /ws
).我尝试使用
handleMessagesWithSinkSource
但在我看来这个 API 的意图是独立生成Sink
和Source
(请参阅路由/ws
)。 I also tried using handleWebSocketMessages
(see route ws/filter
), but to me there is no connection between Sink(inlet) and Source(outlet) in the Flow.我也尝试使用
handleWebSocketMessages
(请参阅路由ws/filter
),但对我来说,Flow 中的 Sink(inlet) 和 Source(outlet) 之间没有连接。 I must be wrong in understanding how Sink
should work here:我理解
Sink
在这里应该如何工作一定是错误的:
my route:我的路线:
(path("ws") & get & pathEndOrSingleSlash) {
extractUpgradeToWebSocket { upgrade =>
complete(upgrade.handleMessagesWithSinkSource(Sink.ignore,
getSourceAll)
} // this route is working fine, pushing all event Messages to client once connected
} ~
(path("ws" / "filter") & get & pathEndOrSingleSlash) {
handleWebSocketMessages(getSourceFiltered)
} // this route I cannot figure out a way to build `Flow` dynamically based on `Sink`...
idea of getSourceAll
and getSourceFiltered
getSourceAll
和getSourceFiltered
的想法
val getSourceAll: Source[Message, NotUsed] = ??? // Stream source genereating Messages based on backend event
val getSourceFiltered: Flow[Message, Message, _] = ??? // the outgoing Source should push Server event messages based on client's "Predicate" message
After the connection being established, I would expect user send over filter like:建立连接后,我希望用户通过以下过滤器发送:
{
productId: 1,
city: New York
}
Then the server should keep pushing data stream(event) in realtime from backend(database) with more detailed product info back to user client:然后服务器应该继续从后端(数据库)实时推送数据流(事件),并将更详细的产品信息返回给用户客户端:
{
orderId: 1122,
productId: 1,
productName: Coke,
vendor: ABC,
city: New York
timestamp: 2019-11-13 09:30:00
}
{
orderId: 3322,
productId: 1,
productName: Coke,
vendor: EFG,
city: New York
timestamp: 2019-11-13 09:31:00
}
...
Is Actor
absolutely required to handle this? Actor
是否绝对需要处理这个问题? if so, any guidance would be really helpful!如果是这样,任何指导都会非常有帮助!
Update In short, how can I emit an event-driven server-push Source based on user's Message?更新简而言之,如何根据用户的消息发出事件驱动的服务器推送源?
Additionally, maybe I am confused on how to build a new Source[Message, _]
?此外,也许我对如何构建新的
Source[Message, _]
感到困惑? I know Flow
is immutable but should be a way to switch based on input( Flow.fromSinkAndSource
?).我知道
Flow
是不可变的,但应该是一种基于输入( Flow.fromSinkAndSource
?)的切换方式。 Because Akka only has directive api like: handleWebSocketMessages(flow: Flow[Message, Message, _])
which only consume the input message, but not produce a new Source
and as for handleMessagesWithSinkSource(sink, source)
the sink and source does not have logical connection to me.因为 Akka 只有指令 api 像:
handleWebSocketMessages(flow: Flow[Message, Message, _])
它只消耗输入消息,但不产生新的Source
,而对于handleMessagesWithSinkSource(sink, source)
接收器和源没有与我的逻辑联系。 I am still trying to wrap my head around how to make it work..我仍在努力思考如何使它工作..
Although it isn't immediately obvious, Flow[Message, Message, _]
is enough for implementing most protocols.虽然不是很明显,但
Flow[Message, Message, _]
足以实现大多数协议。 Remember that a Flow
can build up almost arbitrary amounts of state via functions like statefulMapConcat
or flatMapConcat
.请记住,
Flow
可以通过statefulMapConcat
或flatMapConcat
。 A Flow
can even start emitting stuff without having directly received an input to reply to via functions like extrapolate
or merge
-ing with some ticking source. Flow
甚至可以在没有直接接收到要回复的输入的情况下通过诸如extrapolate
或merge
之类的功能与某些滴答声源开始发出内容。
In your case:在你的情况下:
val getSourceFiltered: Flow[Message, Message, _] = Flow[Message]
.take(1) // you only care about the first thing that the client sends
.flatMapConcat {
case TextMessage.Strict(txtMsg: String) =>
// Here is where you parse and make your filter using the message the client message
val clientFilter: Message => Boolean = makeFilter(txtMsg)
getSourceAll.filter(clientFilter)
case _ => Source.single(TextMessage("Expected a single strict JSON message"))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.