Почему актер начинает дважды? - PullRequest
0 голосов
/ 03 июля 2019

Я запускаю дочерних актеров только один раз следующим образом:

object DetectorSupervisor {

  def create(): Behavior[NotUsed] =
    Behaviors.setup { context =>

      context.log.info(s"=============> Start DetectorSupervisor <=============")

      val informant = context.spawn(InformantActor.create(Vector.empty), "InformantActor")
      val stateMachine = context.spawn(DetectorStateMachine.create(informant,
        State(KafkaInactiveConfirmed, SapInactiveConfirmed)), "StateMachine")

      context.spawn(DetectorReceptionActor.create(informant), "ReceptionActor")

      context.spawn(KafkaDetectorActor.create(stateMachine, None), "KafkaActor")
      context.spawn(SapDetectorActor.create(stateMachine, None), "SapActor")

      Behavior.empty

    }

} 

И в журнале я вижу, что актер всегда начинается дважды.

[INFO] [07/03/2019 22:21:35.513] [testSystem1-akka.actor.default-dispatcher-2] [akka://testSystem1/user/DetectorSupervisor] =============> Start DetectorSupervisor <=============
[INFO] [07/03/2019 22:21:37.456] [testSystem1-akka.actor.default-dispatcher-3] [akka://testSystem1/user/DetectorSupervisor/InformantActor] =============> Start InformantActor <=============
[INFO] [07/03/2019 22:21:37.460] [testSystem1-akka.actor.default-dispatcher-3] [akka://testSystem1/user/DetectorSupervisor/StateMachine] =============> Start DetectorStateMachine <=============
[INFO] [07/03/2019 22:21:37.460] [testSystem1-akka.actor.default-dispatcher-3] [akka://testSystem1/user/DetectorSupervisor/ReceptionActor] =============> Start DetectorReceptionActor <=============
[INFO] [07/03/2019 22:21:37.473] [testSystem1-akka.actor.default-dispatcher-4] [akka://testSystem1/user/DetectorSupervisor/SapActor] =============> Start SapDetectorActor <=============
[INFO] [07/03/2019 22:21:37.473] [testSystem1-akka.actor.default-dispatcher-5] [akka://testSystem1/user/DetectorSupervisor/KafkaActor] =============> Start KafkaDetectorActor <=============
[INFO] [07/03/2019 22:21:37.503] [testSystem1-akka.actor.default-dispatcher-5] [testSystem1] =============> Start KafkaDetectorStream <=============
[INFO] [07/03/2019 22:21:37.503] [testSystem1-akka.actor.default-dispatcher-4] [testSystem1] =============> Start SapDetectorStream <=============
[INFO] [07/03/2019 22:21:43.950] [testSystem1-akka.actor.default-dispatcher-3] [akka://testSystem1/user/DetectorSupervisor/InformantActor] =============> Start InformantActor <============= 

Как видите, InformantActor запускается дважды, и я не мог понять, почему.

Вот реализация InformantActor:

object InformantActor {

  sealed trait InformantEvent

  case object ServerOnlineConfirmed extends InformantEvent

  case object ServerOfflineConfirmed extends InformantEvent

  case class SubscribersChanged(actor: Vector[ActorRef[ServerEvent]]) extends InformantEvent


  def create(subscribers: Vector[ActorRef[ServerEvent]]): Behavior[InformantEvent] =
    Behaviors.setup { context =>

      context.log.info(s"=============> Start InformantActor <=============")

      Behaviors.receiveMessage[InformantEvent] {
        case ServerOfflineConfirmed =>
          subscribers.foreach(a => a ! ServerOfflineApproved)
          Behavior.same
        case ServerOnlineConfirmed =>
          subscribers.foreach(a => a ! ServerOnlineApproved)
          Behavior.same
        case SubscribersChanged(actors) =>
          create(actors)
      }
    }

}

Исходный код размещен на https://gitlab.com/sweetsoft/plugger.

1 Ответ

2 голосов
/ 04 июля 2019

Не думаю, что запускается дважды.

Ваша create функция рекурсивна и выполняется всякий раз, когда происходит case SubscribersChanged(actors) =>.

Поэтому, когда меняется ваш список подписчиков, вы будете видеть ваше сообщение журнала.

Вы рефакторингcreate чтобы исключить сообщение журнала из рекурсии ... примерно так:

def create(initialSubscribers: Vector[ActorRef[ServerEvent]]): Behavior[InformantEvent] = {
  Behaviors.setup { context =>

    context.log.info(s"=============> Start InformantActor <=============")

    def behavior(subscribers: Vector[ActorRef[ServerEvent]]): Behavior[InformantEvent] = Behaviors.receiveMessage[InformantEvent] {
      case ServerOfflineConfirmed =>
        subscribers.foreach(a => a ! ServerOfflineApproved)
        Behavior.same
      case ServerOnlineConfirmed =>
        subscribers.foreach(a => a ! ServerOnlineApproved)
        Behavior.same
      case SubscribersChanged(actors) =>
        behavior(actors)
    }

    behavior(initialSubscribers)
  }
}
...