Akka 有限状态机和如何协议Behaviors.unhandled?

Akka Finite State Machine and how to protocol Behaviors.unhandled?

我有一个关于 Behaviors.unhandled 的问题,我知道 Akka 将未处理的消息发送到死信,并且使用以下配置它也会记录它

akka {
 loglevel = "DEBUG"
 actor {
   debug {
    # enable DEBUG logging of unhandled messages
   unhandled = on
   }
  }
}

这是之前在以下问题 Behaviours.unhandled 中争论过的,并争论 Akka 工作的典型方式,这是可以接受的,也应该只在 DEBUG 级别登录。

在这一点上我来了,有限状态机是 Akka 之上的另一层,在有限状态机概念中,这种情况与未设计的处理转换有关,正如问题的原始发帖者所声称的那样,这是一个非常重要的错误在设计有限状态机的迭代方法中。

Akka FSM 的典型 FSM 配置如下所示,

private val NEW: Behavior[Event] = {
  Behaviors.receive {
    case (ctx, onUserClicked(payload)) =>
      //doSomething()

    case _ => Behaviors.unhandled
  }
}

现在,如果令我们惊讶的是,如果用户设法在 NEW 状态期间生成 onUserDoubleClicked(payload) 事件,那么这是我们这边的设计错误。

问题是,我们大多数人不会 运行 我们的应用程序在生产中处于 DEBUG 级别,如果我们在生产中遇到未处理的转换,我们将永远不会发现它并在下一次迭代中修复。

为了能够跟踪这个我们必须订阅死信根本不会传递给 FSM 概念....

出于这个原因,我认为即使这种情况对于普通 Akka 来说也是可以接受的,使用有限状态机概念,这种情况必须至少记录在 WARN 级别,或者必须提供配置选项来配置行为,或者你看到了吗有没有其他方法可以在不造成大量代码混乱的情况下实现这一目标?

我不确定这是否是您问题的最准确答案,但我将分享对我们这个用例有用的东西。

看看这个:https://github.com/bilal-fazlani/fsm-with-akka-typed

我们尝试使用 akka typed 为 FSM 提取模式。此模式的关键是自定义接收函数,即 myReceive.

这不仅允许我们自己在任何级别记录未处理的消息,还可以向发件人发送回复,告知他们的消息是未处理的。这种模式的另一个好处是——因为我们创建了单独的消息层次结构,例如 ReadBehaviorMessageWriteBehaviorMessage,我们现在被迫处理所有消息 "of a particular state";否则编译器会显示警告。

根据前面回答中给出的提示和我自己的想法使用AspectJ来识别代码到达的地方'unhandled'行为,我开发了一个Aspect来捕获Akka有限状态机中的未处理事件,这有助于在迭代方法中识别缺失的设计元素和错误。

您可以在我的 blog 中找到实现细节,其中解释了 AspectJ 如何在 Scala 状态机中提供帮助。

它捕获未处理的调用时刻并帮助识别处于哪个状态、未处理的转换到达、事件负载是什么以及此状态下保存的信息快照。