Akka is an awesome tool, even using default configuration, you do not have anymore to worry about failure management and recovery details. I've been bluffed to discover that my new monitoring system prototype (akka/scala based) was able to recovery by itself from errors, while I didn't yet implement such features !!

So In order to illustrate this feature, I've written a simple example that illustrates this behavior. The RobustActor actor keeps a ssh connection to a remote system (using janalyse-ssh scala ssh api), and execute/print every 5s the "date" command :

package dummy

import akka.actor.ActorSystem
import akka.actor.Actor
import akka.util.duration._
import com.typesafe.config.ConfigFactory
import akka.actor.Props

import fr.janalyse.ssh._

object DummySSH {
def main(args:Array[String]) {
val system=ActorSystem("DummySSHSystem",ConfigFactory.load.getConfig("dummySSH"))
system.actorOf(
Props(new RobustActor(system)),
name="RobustActor")
}
}


class RobustActor(system:ActorSystem) extends Actor {

val sh = SSH(host="localhost", username="test", password=Some("testtest")).newShell

override def preStart() {
system.scheduler.schedule(1 seconds, 5 seconds, self, "doit")
}

override def postStop() {
sh.close()
}

def receive = {
case "doit" => print(sh execute "date")
}
}
If we start this example code, we wait a little, we identify the sshd process that manages the established ssh connection and then we kill the sshd process, akka will intercept RobustActor internal exception and restart this actor for us !

$ sbt run
[info] Loading project definition from /home/dcr/dev-new/akka-sandbox/project
[info] Set current project to AkkaSandbox (in build file:/home/dcr/dev-new/akka-sandbox/)
[info] Compiling 1 Scala source to /home/dcr/dev-new/akka-sandbox/target/scala-2.9.1/classes...

Multiple main classes detected, select one to run:

[1] dummy.Dummy
[2] dummy.DummySSH

Enter number: 2

[info] Running dummy.DummySSH
dim. avril 1 22:15:32 CEST 2012
dim. avril 1 22:15:37 CEST 2012
dim. avril 1 22:15:42 CEST 2012
dim. avril 1 22:15:47 CEST 2012
[ERROR] [04/01/2012 22:15:53.92] [DummySSHSystem-akka.actor.default-dispatcher-3] [akka://DummySSHSystem/user/RobustActor] Pipe closed
java.io.IOException: Pipe closed
at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:244)
at java.io.PipedInputStream.receive(PipedInputStream.java:210)
at java.io.PipedOutputStream.write(PipedOutputStream.java:132)
at java.io.OutputStream.write(OutputStream.java:58)
at fr.janalyse.ssh.SSHShell$Producer.sendCommand(SSHAPI.scala:480)
at fr.janalyse.ssh.SSHShell.sendCommand(SSHAPI.scala:475)
at fr.janalyse.ssh.SSHShell.execute(SSHAPI.scala:448)
at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:34)
at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:33)
at akka.actor.Actor$class.apply(Actor.scala:290)
at dummy.RobustActor.apply(DummySSH.scala:21)
at akka.actor.ActorCell.invoke(ActorCell.scala:617)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:179)
at akka.dispatch.Mailbox.run(Mailbox.scala:161)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:505)
at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259)
at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:997)
at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1495)
at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

dim. avril 1 22:15:54 CEST 2012
dim. avril 1 22:15:58 CEST 2012


To identify the process which manages our example ssh connection, just use the following commands, list all sshd processes which belongs to test user, then take the process that do not use your current test shell session.

test@lanfeust ~ $ ps -ef | grep "^test"
test 8824 8815 0 11:20 ? 00:00:00 sshd: test@pts/7
test 8825 8824 0 11:20 pts/7 00:00:00 -bash
test 32468 32458 0 22:15 ? 00:00:00 sshd: test@pts/8
test 32469 32468 0 22:15 pts/8 00:00:00 -bash
test 32474 8825 0 22:15 pts/7 00:00:00 ps -ef
test 32475 8825 0 22:15 pts/7 00:00:00 grep --colour=auto ^test
test@lanfeust ~ $ tty
/dev/pts/7
test@lanfeust ~ $ kill -9 32468
test@lanfeust ~ $

This example source code is available here : akka-sandbox