处理Akka应用程序中的每个事件

处理Akka应用程序中的每个事件 这里的事件,那里的事件,到处都是事件。 发布有关检查每一项Akka事件最终都能找到归宿的信息。

Akka和基于事件的反应式应用程序是创建软件的新方法。 在当前基于Scala的项目中,我们非常密集地使用Akka。 事件非常适合我们的用例,因为我们正在与外部API通信,这可能很慢。 使用传统的同步方法处理时,这可能会损害用户体验。 但是幸运的是,我们的请求可以异步执行,因此将它们传递给Actor似乎是一个好主意。

当事情得到控制时

但是,事件虽然很酷并且非常有用,但是如果没有经验的人来处理,事件仍然会伤害项目。 异步性质使应用程序流程乍一看很难理解。 而且,每当您向系统中添加新的参与者或事件类型时,您忘记正确处理某件事的可能性就会增加。

让我们看一下示例类,这是一个处理与Image标签和注释关联的事件的actor:

class YourActor extends Actor {
    override def receive = {
        case event: ImageTagged =>
          doSomething()
        case event: OtherImageTaggedByFriend =>
          doSomething2()
        case event: MostMotedUserImage =>
          doSomething3()
        case event: MostCommentedFriendImageChosen =>
          doSomething4()
      }
}

当您添加下一个事件时,例如说MostLikedFriendImage,您可以轻松地忘记在actor中添加处理程序案例部分,尤其是当有多个actor监听此类事件时。

干违规溶液

有一种简单的解决方案可以检测遗忘的处理程序。 我们可以将case _添加到每个actor:

class YourActor extends Actor {
    override def receive = {
        case event: ImageTagged =>
          doSomething()
        case event: OtherImageTaggedByFriend =>
          doSomething2()
        case event: MostMotedUserImage =>
          doSomething3()
        case event: MostCommentedFriendImageChosen =>
          doSomething4()
        case event: _ :
          logger.error("Received unknown event " + event.getClass.toString)
      }
}

虽然对于一个或两个参与者来说看起来还可以,但将相同的代码片段添加到多个参与者中却很麻烦,并且违反了DRY原则。 但是,最危险的是,您团队中的某个人可能会忘记添加它(就像有人说的那样: “每个可以被遗忘的手动任务都会被遗忘” )。 那么也许我们应该寻求更好的解决方案?

对任何未处理的事件做出反应

处理Akka应用程序中的每个事件

幸运的是,我们不会停留在容易出错的方法上。 当actor无法处理传递给他的事件时,将引发UnhandledMessage并将其发布到ActorSystem的EventStream。

因此,要处理每个被遗忘的事件,我们可以创建侦听器并将其订阅到EventStream:

class UnhandledMessageListener extends Actor {

  val logger = LoggerFactory.getLogger(getClass)


  override def receive = {
    case message: UnhandledMessage =>
      logger.error(s"CRITICAL! No actors found for message ${message.getMessage}"))

      if (!Environment.isProduction) {
        // Fail fast, fail LOUD
        logger.error("Shutting application down")
        System.exit(-1)
      }
  }
}

并订阅代码片段:

val actorSystem = ActorSystem.create("projectActorSystem")

 val listener = actorSystem.actorOf(Props(new UnhandledMessageListener()))
 actorSystem.eventStream.subscribe(listener, classOf[UnhandledMessage])

就是这样。 现在,每当有一个参与者没有处理的事件时,我们都会知道这一点,尤其是在非生产环境中部署应用程序时!

翻译自: https://www.javacodegeeks.com/2014/06/handle-every-event-in-your-akka-application.html