Обмен данными между актерами Akka - PullRequest
0 голосов
/ 25 сентября 2019

На основании этого вопроса Обмен данными в Akka Я реализовал простую иерархию akka для обмена данными между двумя участниками:

package playground

import akka.actor.{Actor, ActorRef, ActorSystem, Props}

case object GetFromDb
case object GetList
case object ProcessList

class ParentActor extends Actor {
  var fromDb: List[Int] = List()

  def receive = {
    case GetFromDb =>
      // query the database and replace fromDb with a new list
      fromDb = List(1,2,3)

    case GetList =>
      sender() ! fromDb
  }
}

class ChildActor(parent: ActorRef) extends Actor {
  def receive = {
    case ProcessList =>
      // get the list from the parent
      parent ! GetList
    case fromDb: List[Int] =>
      fromDb.foreach(println)
  }
}

object AkkaDataSharingDriver extends App {

  val system: ActorSystem = ActorSystem("as")
  implicit val ec = system.dispatcher

  val parentActorRef: ActorRef = system.actorOf(Props(new ParentActor()))
  val childActorRef: ActorRef = system.actorOf(Props(new ChildActor(parentActorRef)))

  parentActorRef ! GetFromDb
  parentActorRef ! GetList

  childActorRef ! ProcessList

}

Значения списка 1,2,3 являютсянапечатано так, что кажется, что сообщение fromDb отправлено ChildActor, что вызывает foreach:

case fromDb: List[Int] =>
      fromDb.foreach(println)

Но так как сообщение с fromDb никогда не отправляется явно, что вызывает

fromDb.foreach(println)

будет вызван?Это как-то отправлено неявно?

1 Ответ

1 голос
/ 25 сентября 2019

Имя ребенка / родителя довольно запутанное, так как в этом коде нет отношений родитель / ребенокЛучше назвать их как DbProvider и DbClient.

Последовательность такова:

  1. Приложение отправляет ProcessList дочернему актеру (childActorRef ! ProcessList)
  2. Дочерний актер отправляет GetList родительскому актеру (parent ! GetList)
  3. Родительский актер отвечает дочернему актеру с помощью db (sender() ! fromDb)
  4. Дочерний актер получаетдБ и распечатывает его

Обратите внимание, что в этом коде есть условие гонки, и теоретически дБ может быть List(), а не List(1,2,3).


ЕдинственноеГарантия доставки в Akka заключается в том, что два сообщения, отправленные одним и тем же актером, будут обрабатываться в том порядке, в котором они были отправлены.В противном случае сообщения могут быть обработаны в любом порядке, и, в частности, сообщения, отправленные через третьего участника, могут опередить сообщения, отправленные напрямую.

В этом случае сообщение ProcessList может быть обработано ChildActor ирезультирующее сообщение GetList может быть обработано ParentActor до того, как сообщение GetFromDb из приложения обработано ParentActor.Если это произойдет, ответ на GetList будет содержать значение БД по умолчанию.

...