Akka 在流的生存期内缓存已处理的消息

Akka 在流的生存期内缓存已处理的消息,akka,akka-stream,akka-http,Akka,Akka Stream,Akka Http,我正在重做上一个问题,以使其更加集中和明确。 我有以下情况: case class Hello(u:String) extends A case class Goodbye extends A case class GoodbyeAck(u:String) extends B val myProcessor: Flow[A, B, Unit] = Flow[A] .map { case Hello(u:String) => // I want to cache u

我正在重做上一个问题,以使其更加集中和明确。 我有以下情况:

case class Hello(u:String) extends A
case class Goodbye extends A
case class GoodbyeAck(u:String) extends B

 val myProcessor: Flow[A, B, Unit] =  Flow[A]
    .map {
      case Hello(u:String) => // I want to cache u (the username)
      case Goodbye => GoodbyeAck(u)
    }
因此,在流的开始,我得到一个Hello(用户名),在流的结尾,我收到一个再见。我想用再见(用户名)回复


我应该如何缓存用户名(u),使其在流的生命周期内可用,以便在该说再见时可以使用它?有什么背景我可以利用吗?或者我需要在框架之外做吗?

这似乎是少数几个需要可变状态的例子之一。虽然不是“纯粹的功能”,但状态可以以不允许外部影响的方式隔离,但仍然可以提供您正在寻找的功能

注意:您的问题没有指定在接收Hello时map应该返回什么B值。类型B的值是必需的,因为简单缓存的类型是Unit。因此,flatMapConcat用于符合问题中流程的要求,即在收到Hello时不返回任何内容:

def cacheProcessor(defaultString : String = "") : Flow[A, B, Unit] = {

  var userCache : String = defaultString

  Flow[A] flatMapConcat {
    case Hello(u : String) => {
      userCache = u
      Source.empty[B]
    }
    case Goodbye => Source.single[B](GoodbyeAck(userCache))
  }
}//end def cacheProcessor

尽管userCache是可变状态,但无法在返回的Flow.flatMapConcat之外访问它。重要的一点是,cacheProcessor必须是
def
,这样每个流都有一个唯一的
userCache

既然这是只附加数据,你就不能列出你遇到的用户名吗?谢谢。我想修复比预期的要容易(我已经将我的流作为def,但前一个流不是出于某种原因,所以它会影响我的结果。您的回答让我相信我走的是正确的道路,所以我重新编写了代码)。不过,我认为这对akka http用户来说有点不雅观,希望会有一些关于更优雅的服务器端会话状态的规定。@WillIAm欢迎您。我同意这是“有点不雅”。我经常考虑一个Flow.map,它根据一个标准更改映射的函数,类似于Actor的been/unbecome功能。然而,有时一个简单的副作用函数比一个卷积的无副作用函数要好。我认为scala的美妙之处在于,两个世界中最好的总是可以得到的,即使其中一个通常是首选的。好吧,上面的解决方案的问题是,它不能跨多个流和多个阶段进行扩展。据我所知,“缓存”是特定流的本地缓存。所以,如果我有更复杂的缓存需求,我现在可能不得不避免akka-*了,这太令人头痛了。但它适合我目前的需要@WillIAm如果你想要一个跨流可用的缓存,那么我想代理回答你的另一个问题是你最好的选择。。。