txx
txx

Reputation: 81

How to detect dead remote client or server in akka2

Im new to AKKA2.The following is my question:

There is a server actor and several client actors. The server stores all the ref of the client actors.

I wonder how the server can detect which client is disconnected(shutdown, crash...)

And if there is a way to tell the clients that the server is dead.

Upvotes: 1

Views: 1606

Answers (3)

Viktor Klang
Viktor Klang

Reputation: 26579

In the upcoming Akka 2.2 release (RC1 was released yesterday), Death Watch works both locally and remote. If you watch the root guardian on the other system, when you get Terminated for him, you know that the remote system is down.

Hope that helps!

Upvotes: 1

Sergii Vozniuk
Sergii Vozniuk

Reputation: 222

In order to make your server react to changes of remote client status you could use something like the following (example is for Akka 2.1.4).

In Java

@Override
public void preStart() {
    context().system().eventStream().subscribe(getSelf(), RemoteLifeCycleEvent.class);
}

Or in Scala

override def preStart = {
     context.system.eventStream.subscribe(listener, classOf[RemoteLifeCycleEvent])
}

If you're only interested when the client is disconnected you could register only for RemoteClientDisconnected

More info here(java)and here(scala)

Upvotes: 1

jxstanford
jxstanford

Reputation: 3387

There are two ways to interact with an actor's lifecycle. First, the parent of an actor defines a supervisory policy that handles actor failures and has the option to restart, stop, resume, or escalate after a failure. In addition, a non-supervisor actor can "watch" an actor to detect the Terminated message generated when the actor dies. This section of the docs covers the topic: http://doc.akka.io/docs/akka/2.0.1/general/supervision.html

Here's an example of using watch from a spec. I start an actor, then set up a watcher for the Termination. When the actor gets a PoisonPill message, the event is detected by the watcher:

"be able to watch the proxy actor fail" in {
      val myProxy = system.actorOf(Props(new VcdRouterActor(vcdPrivateApiUrl, vcdUser, vcdPass, true, sessionTimeout)), "vcd-router-" + newUuid)
      watch(myProxy)
      myProxy ! PoisonPill
      expectMsg(Terminated(`myProxy`))
}

Here's an example of a custom supervisor strategy that Stops the child actor if it failed due to an authentication exception since that probably will not be correctable, or escalates the failure to a higher supervisor if the failure was for another reason:

override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 5, withinTimeRange = 1 minutes) {

    // presumably we had a connection, and lost it.  Let's restart the child and see if we can re-establish one.
    case e: AuthenticationException ⇒
      log.error(e.message + "  Stopping proxy router for this host")
      Stop

    // don't know what it was, escalate it.
    case e: Exception ⇒
      log.warning("Unknown exception from vCD proxy. Escalating a {}", e.getClass.getName)
      Escalate
}

Within an actor, you can generate the failure by throwing an exception or handling a PoisonPill message.

Another pattern that may be useful if you don't want to generate a failure is to respond with a failure to the sender. Then you can have a more personal message exchange with the caller. For example, the caller can use the ask pattern and use an onComplete block for handling the response. Caller side:

vcdRouter ? DisableOrg(id) mapTo manifest[VcdHttpResponse] onComplete {
      case Left(failure) => log.info("receive a failure message")  
      case Right(success) ⇒ log.info("org disabled)    
}

Callee side:

val org0 = new UUID("00000000-0000-0000-0000-000000000000")
def receive = {
  case DisableOrg(id: UUID) if id == org0 => sender ! Failure(new IllegalArgumentException("can't disable org 0")
  case DisableOrg(id: UUID) => sender ! disableOrg(id)
}

Upvotes: 2

Related Questions