How can i check if an Akka actor exists (akka 2.2)?

两盒软妹~` 提交于 2019-11-30 00:11:19

It looks like Akka left off support for ActorSelection on the java api for ask. I played with the code a little and I found something that works though. See if this code works for you:

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

I just looked at how the scala ask support worked and hooked into it via java. This worked for me; I'm hoping it works for you.

I recently found the ActorSelection.resolveOne method:

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
}

One problem I'm still investigating is, the method where this is defined might be called concurrently (from other actors). Therefore it's possible to get a race condition where you try to create the actor twice if the resolveOne call fails because the actor is still being created. This might or might not be an issue for your use case

Akka provides a functionality to get an ActorRef from an ActorSelection using a special message Identify. You don't have to use ask() for this message. Simply pass an Identify-message to the ActorSelection and listen for an ActorIdentity message that will be passed back to you. There is an example for exactly this in the Akka docs: Identifying Actors via Actor Selection (Java)

This code is taken from the example and modified:

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

There is also a very nice graphic that shows the relations between ActorPath, ActorSelection and the Actor Lifecycle in the docs.

Daniel Winterstein

As other answers note, ActorSelection.resolveOne() handles this.

One warning: Under the hood, this works by sending a message to the actor in question. Which means if that actor is busy, it won't reply, and this fails (with a timeout).

In pure-best-practice-Akka, this is probably a corner-case. In a more mixed normal-Java / Akka setup, it's easy to get snarled up though. In particular, code within an actor's thread cannot find a reference to that actor.

Using version 2.3.4

Some Scala example, maybe can help

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

  val x = zed2.resolveOne(fs).value
  if (x.isDefined){
    println(x.get.isFailure)
  }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!