Scala 什么';在Redis pub/sub和Akka Streams中使用SSE的最简单方法是什么?

Scala 什么';在Redis pub/sub和Akka Streams中使用SSE的最简单方法是什么?,scala,redis,akka,akka-stream,akka-http,Scala,Redis,Akka,Akka Stream,Akka Http,我想为以下场景流式处理分块服务器发送的事件: 订阅Redis密钥,如果密钥发生更改,则使用Akka Streams流传输新值。仅当存在新值时,才应流式处理 据我所知,我需要一个源代码。我猜这是对一个频道的订阅: redis.subscriber.subscribe("My Channel") { case message @ PubSubMessage.Message(channel, messageBytes) => println( message.readAs[Strin

我想为以下场景流式处理分块服务器发送的事件:

订阅Redis密钥,如果密钥发生更改,则使用Akka Streams流传输新值。仅当存在新值时,才应流式处理

据我所知,我需要一个
源代码。我猜这是对一个频道的订阅:

redis.subscriber.subscribe("My Channel") {
  case message @ PubSubMessage.Message(channel, messageBytes) => println(
    message.readAs[String]()
  )
  case PubSubMessage.Subscribe(channel, subscribedChannelsCount) => println(
    s"Successfully subscribed to $channel"
  )
}
在我的过程中,我需要从中创建一个
源代码
,但老实说,我不知道如何开始:

val route: Route =
  path("stream") {
   get {
     complete {
       val source: Source[ServerSentEvent, NotUsed] =
         Source
          .asSubscriber(??) // or fromPublisher???
      .map(_ => {
        ??
      })
      .map(toServerSentEvent)
      .keepAlive(1.second, () => ServerSentEvent.heartbeat)
      .log("stream")
     }
   }
一种方法是使用和:

将物化的
ActorRef
订阅到您的消息通道:发送给此参与者的消息将在下游发出。如果没有下游需求,则使用指定的溢出策略将消息缓冲到一定数量(在本例中,缓冲区大小为10)。请注意,这种方法没有背压

redis.subscriber.subscribe("My Channel") {
  case message @ PubSubMessage.Message(channel, messageBytes) =>
    val strMsg = message.readAs[String]
    println(strMsg)
    sseActor ! strMsg

  case ...
}
还要注意,上面的示例使用了
Source.actorRef[String]
;根据需要调整类型和示例(例如,它可以是
Source.actorRef[pubsubsubmessage.Message]

您可以在路径中使用具体化的
源代码

path("stream") {
  get {
    complete(sseSource)
  }
}

另一种方法是创建一个源作为队列,并在订阅者回调中向队列提供接收到的元素

val queue =
  Source
    .queue[String](10, OverflowStrategy.dropHead) // drops the oldest element from the buffer to make space for the new element.
    .map(toServerSentEvent) // converts a String to a ServerSentEvent
    .keepAlive(1.second, () => ServerSentEvent.heartbeat)
    .to(Sink.ignore)
    .run()
在订户中

    redis.subscriber.subscribe("My Channel") {
  case message @ PubSubMessage.Message(channel, messageBytes) =>
    val strMsg = message.readAs[String]
    println(strMsg)
    queue.offer(strMsg)

  case ...
}

谢谢你!它就像一个符咒。但在日志中,我现在看到了这一点:
在收到请求结束之前发送2xx“早期”响应。。。请注意,此响应后连接将关闭。此外,许多客户不会阅读早期回复!请考虑在请求数据已完全读取之后发出此响应!
这可能是因为在
subscribe
中,我正在推出我的对象的初始状态以供客户端设置。有什么办法可以预防吗?谢谢你,对我来说很好。有没有可能更改事件类型名称?当前是
消息
。如何处理断开连接?当客户端关闭连接时,Redis订阅仍然处于活动状态,并且您的参与者将继续处理消息,即使没有人使用它们
    redis.subscriber.subscribe("My Channel") {
  case message @ PubSubMessage.Message(channel, messageBytes) =>
    val strMsg = message.readAs[String]
    println(strMsg)
    queue.offer(strMsg)

  case ...
}