Jak mogę sprawdzić, czy aktor Akka istnieje (akka 2.2)?

Mam obiekt java, który nie jest aktorem, który wybiera aktorów z systemu aktora z actorSelection(ścieżka)). Możliwe, że wybrany aktor nie istnieje w systemie.

W Java Api ask() nie istnieje dla ActorSelection, więc nie mogę wysłać i zidentyfikować Wiadomości do wyboru aktora i użyć nadawcy odpowiedzi.

Próbowałem rozwiązać problem, wysyłając wiadomość do aktora i tak poprzez wybór aktora, a następnie reagując na deadletter. Ale nie mam żadnych deadletterów.

Jak mogę sprawdzić u aktora, czy aktor żyje lub nie istnieje?

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);
Author: schrums, 2013-08-02

5 answers

Wygląda na to, że Akka przestała wspierać ActorSelection W java api dla ask. Pobawiłem się trochę kodem i znalazłem coś, co działa. Sprawdź, czy ten kod działa dla Ciebie:

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);
  }
}

Po prostu spojrzałem na to, jak działa wsparcie Scala ask i podłączyłem się do niego za pomocą Javy. To zadziałało na mnie, mam nadzieję, że zadziała na Ciebie.

 12
Author: cmbaxter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-02 12:00:49

Znalazłem Ostatnio ActorSelection.metoda 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
}

Jeden problem nadal badam jest, metoda, w której jest to zdefiniowane może być nazywany jednocześnie (od innych podmiotów). Dlatego możliwe jest uzyskanie warunku race, w którym próbujesz utworzyć aktora dwa razy, jeśli resolveOne call nie powiedzie się, ponieważ aktor jest nadal tworzony. To może, ale nie może być problemem w przypadku użycia

 22
Author: Mario Camou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-07 10:51:13

Akka dostarcza funkcjonalność do pobierania ActorRef z ActorSelection za pomocą specjalnego komunikatu Identify. Nie musisz używać ask() do tej wiadomości. Po prostu Przekaż wiadomość identyfikacyjną do ActorSelection i posłuchaj wiadomości ActorIdentity, która zostanie Ci przekazana. W Akka docs znajduje się przykład na to: identyfikowanie aktorów poprzez selekcję aktorów (Java)

Ten kod jest zaczerpnięty z przykładu i zmodyfikowany:

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
            }
        }
     }
}

Jest też bardzo ładnagrafika to pokazuje relacje między ścieżką aktora, wyborem aktora i cyklem życia aktora w dokumentach.

 5
Author: Björn Jacobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-02 11:34:25

Jak Inne odpowiedzi zauważ, ActorSelection.resolveOne() radzi sobie z tym.

Jedno ostrzeżenie: pod maską działa to poprzez wysłanie wiadomości do danego aktora. Co oznacza, że jeśli ten aktor jest zajęty, nie odpowie, a to nie powie (z timeoutem).

W czystej-najlepszej-praktyce-Akka, to prawdopodobnie sprawa narożna. W bardziej wymieszanej konfiguracji normal-Java / Akka łatwo się jednak warczy. W szczególności kod w wątku aktora nie może znaleźć odniesienia do tego aktora.

 3
Author: Daniel Winterstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-11 10:38:29

Korzystanie z wersji 2.3.4

Jakiś przykład Scali, może pomoże

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

  val x = zed2.resolveOne(fs).value
  if (x.isDefined){
    println(x.get.isFailure)
  }
 0
Author: Ivan Gonzalez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 23:28:08