Как получить актера внутри другого актера без блокировки? - PullRequest
0 голосов
/ 26 апреля 2018

В настоящее время в существующем проекте scala akka-http у нас есть группа актеров, которые должны сообщать другим акторам сообщения.

В актере мы получили бы ссылку актера через:

class OurActor extends Actor {
     private implicit val timeout: Timeout = 15.seconds
     private val otherActor: ActorRef = Await.result[ActorRef](context.system.actorSelection("path/to/other/actor").resolveOne()(timeout), 15.seconds)

       override def receive: Receive = {
    case SomeMessage => {
      ...
      dataSets.foreach(_.foreach(otherActor ! _))
    }
  }
}

Меня немного смущает использование Await.result, так как это блокирует в текущем потоке. Какую альтернативу я могу использовать?

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Вы можете добавить другого актора в качестве параметра конструктора OurActor

object OurActor {
  def props(otherActorRef: ActorRef) = Props(classOf[OurActor],otherActorRef)
}


class OurActor(otherActor: ActorRef) extends Actor {
     private implicit val timeout: Timeout = 15.seconds

       override def receive: Receive = {
    case SomeMessage => {
      ...
      otherActor ! _
    }
  }
}

Когда вы создаете экземпляр своего актера:

val otherActor = actorSystem.actorOf(OtherActor.props, "otherActor")
val ourActor   = actorSystem.actorOf(OurActor.props(otherActor) "ourActor")
0 голосов
/ 26 апреля 2018

Если вы хотите убедиться, что это разрешимо, возможно, вы можете сделать dataSets.foreach непосредственно внутри Future. Примерно так:

class OurActor extends Actor {
    override def receive: Receive = {
        case SomeMessage => {
            ...
            context.system.actorSelection("path/to/other/actor").resolveOne().map { actorRef => 
                dataSets.foreach(_.foreach(actorRef ! _))
            }
        }
    }
}

Это означает, что оператор dataSets.foreach будет выполняться асинхронно. Вам нужно быть осторожным, если dataSets изменчив, поскольку все будет работать в разных потоках. Кроме того, Future может завершиться ошибкой, поэтому вы можете также учитывать этот сценарий.

0 голосов
/ 26 апреля 2018

Вам не обязательно нужен actorRef, но вы также можете отправлять сообщения актеру (или даже нескольким актерам), используя селектор напрямую:

class MetronomeJobAlertActor extends Actor {
  private implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))
  private implicit val ec = context.dispatcher
  private implicit val sys = context.system
  private val otherActorSelection: ActorSelection = context.system.actorSelection("path/to/other/actor")

  override def receive: Receive = {
    case SomeMessage => {
      ...
      dataSets.foreach(otherActorSelection ! _))
  }
}
...