簡體   English   中英

Akka HTTP WebSocket Server 構建消息處理流時如何根據 Sink 內容聲明 Source?

[英]Akka HTTP WebSocket Server How to declare Source based on Sink content when building Flow for message handlement?

我正在玩 Akka Stream/Http 並試圖弄清楚如何在 websocket 服務器中執行以下操作(希望不使用 Actor 模式):

1.客戶端初始連接請求,握手后,服務器會監聽客戶端的初始Message ,格式為json
2. 服務器收到TextMessage.Strict后,如果有效,它將豐富Message以構建“謂詞”(例如過濾器映射),然后服務器將使用該“謂詞”構建Source[Message, _]

我嘗試使用handleMessagesWithSinkSource但在我看來這個 API 的意圖是獨立生成SinkSource (請參閱路由/ws )。 我也嘗試使用handleWebSocketMessages (請參閱路由ws/filter ),但對我來說,Flow 中的 Sink(inlet) 和 Source(outlet) 之間沒有連接。 我理解Sink在這里應該如何工作一定是錯誤的:

我的路線:

              (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`...


getSourceAllgetSourceFiltered的想法

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 

建立連接后,我希望用戶通過以下過濾器發送:

{
 productId: 1,
 city: New York
}

然后服務器應該繼續從后端(數據庫)實時推送數據流(事件),並將更詳細的產品信息返回給用戶客戶端:

{
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
}
...

Actor是否絕對需要處理這個問題? 如果是這樣,任何指導都會非常有幫助!

更新簡而言之,如何根據用戶的消息發出事件驅動的服務器推送源?

此外,也許我對如何構建新的Source[Message, _]感到困惑? 我知道Flow是不可變的,但應該是一種基於輸入( Flow.fromSinkAndSource ?)的切換方式。 因為 Akka 只有指令 api 像: handleWebSocketMessages(flow: Flow[Message, Message, _])它只消耗輸入消息,但不產生新的Source ,而對於handleMessagesWithSinkSource(sink, source)接收器和源沒有與我的邏輯聯系。 我仍在努力思考如何使它工作..

雖然不是很明顯,但Flow[Message, Message, _]足以實現大多數協議。 請記住, Flow可以通過statefulMapConcatflatMapConcat Flow甚至可以在沒有直接接收到要回復的輸入的情況下通過諸如extrapolatemerge之類的功能與某些滴答聲源開始發出內容。

在你的情況下:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM