Как я могу проверить, существует ли аккский актер (акка 2.2)?

У меня есть объект java, который не является актером, который выбирает актеров из актерской системы с помощью actorSelection (Path)). Возможно, что выбранный актер не существует в системе.

В Java Api ask() не существует для ActorSelection, поэтому я не могу отправить и идентифицировать сообщение для выбора актера и использовать отправителя ответа.

Я попытался решить проблему, отправив сообщение актеру в любом случае с помощью выбора актера, а затем отреагировав на прописку. Но я не получаю никаких сводок.

Как я могу проверить с помощью ActorSelection, если актер жив или не существует?

ActorSystem system = ActorSystem.create("test");

//create test actor
system.actorOf(Props.create(TestActor.class), "testActor");

//add dead letter listener to the system
ActorRef eventBusActor = asys.actorOf(Props.create(EventBusActor.class), "eventbusactor");
system.eventStream().subscribe(eventBusActor, DeadLetter.class);


//This works. The test actor receives the message      
ActorSelection a1 = asys.actorSelection("/user/testActor");
a1.tell("hello", ActorRef.noSender());

//This does not work and does not send dead letters      
ActorSelection a2 = asys.actorSelection("/user/doesnotexist");
a2.tell("hello", ActorRef.noSender());

//Does not compile, because ask needs an ActorRef as first argument
ActorSelection a3 = asys.actorSelection("/user/test");
Future f = Patterns.ask(a3, new Identify(), 1000);

Ответы

Ответ 1

Похоже, Akka отказался от поддержки ActorSelection на java api для ask. Я немного сыграл с кодом, и я нашел что-то, что работает. Посмотрите, работает ли этот код для вас:

import java.util.concurrent.TimeUnit;

import scala.concurrent.Await;
import scala.concurrent.Future;

import akka.actor.ActorIdentity;
import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
import akka.actor.Identify;
import akka.actor.Props;
import akka.pattern.AskableActorSelection;
import akka.util.Timeout;

public class AskTest {

  public static void main(String[] args) throws Exception{
    ActorSystem sys = ActorSystem.apply("test");
    sys.actorOf(Props.create(TestActor.class), "mytest");

    ActorSelection sel = sys.actorSelection("/user/mytest");

    Timeout t = new Timeout(5, TimeUnit.SECONDS);
    AskableActorSelection asker = new AskableActorSelection(sel);
    Future<Object> fut = asker.ask(new Identify(1), t);
    ActorIdentity ident = (ActorIdentity)Await.result(fut, t.duration());
    ActorRef ref = ident.getRef();
    System.out.println(ref == null);
  }
}

Я просто посмотрел, как работала поддержка scala поддержки и подключалась к ней через java. Это сработало для меня; Я надеюсь, что это сработает для вас.

Ответ 2

Недавно я нашел метод ActorSelection.resolveOne:

val name = "myActor"
implicit val timeout = 5000 // Timeout for the resolveOne call
system.actorSelection(name).resolveOne().onComplete {
  case Success(actor) => actor ! message

  case Failure(ex) =>
    val actor = system.actorOf(Props(classOf[ActorClass]), name)
    actor ! message
}

Одна проблема, которую я все еще изучаю, - метод, в котором это определено, можно назвать одновременно (от других участников). Поэтому можно получить условие гонки, когда вы пытаетесь создать актера дважды, если вызов resolveOne завершится неудачно, потому что актер все еще создается. Это может быть или не быть проблемой для вашего случая использования

Ответ 3

Akka предоставляет функциональные возможности для получения ActorRef из ActorSelection с помощью специального сообщения Identify. Вам не нужно использовать ask() для этого сообщения. Просто передайте Identify-сообщение в ActorSelection и прослушайте сообщение ActorIdentity, которое будет передано вам. Вот пример этого в документах Akka: Идентификация актеров с помощью выбора актера (Java)

Этот код взят из примера и изменен:

final String identifyId = "1";

@Override
public void onReceive(Object message) {
    if (message instanceof ActorIdentity) {
        ActorIdentity identity = (ActorIdentity) message; 
        if (identity.correlationId().equals(identifyId)) {
            ActorRef ref = identity.getRef();
            if (ref == null)
                // Actor does not exist
            else {
                // Actor does exist
            }
        }
     }
}

Существует также очень приятный график, который показывает отношения между ActorPath, ActorSelection и жизненным циклом актера в документах.

Ответ 4

Как отмечают другие ответы, ActorSelection.resolveOne() обрабатывает это.

Одно предупреждение: под капотом это работает, отправив сообщение соответствующему актеру. Это означает, что если этот актер занят, он не будет отвечать, и это не сработает (с таймаутом).

В чистом-лучшем случае - Akka, это, вероятно, краеугольный камень. В более смешанной настройке normal-Java/Akka легко получить рычание. В частности, код в потоке актера не может найти ссылку на этого участника.

Ответ 5

Использование версии 2.3.4

Пример Scala, возможно, может помочь

  val zed2 = Akka.system().actorSelection("path")
  val fs:FiniteDuration = (100).millis

  val x = zed2.resolveOne(fs).value
  if (x.isDefined){
    println(x.get.isFailure)
  }