2011-12-19 11:07:59 +01:00
|
|
|
/**
|
2013-01-09 01:47:48 +01:00
|
|
|
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
2011-12-19 11:07:59 +01:00
|
|
|
*/
|
2012-05-22 11:37:09 +02:00
|
|
|
package docs.actor;
|
2011-12-15 23:33:15 +01:00
|
|
|
|
|
|
|
|
//#testkit
|
|
|
|
|
import akka.actor.ActorRef;
|
|
|
|
|
import akka.actor.ActorSystem;
|
2012-01-23 17:18:49 +01:00
|
|
|
import akka.actor.SupervisorStrategy;
|
2012-10-16 14:38:23 +02:00
|
|
|
import static akka.actor.SupervisorStrategy.resume;
|
|
|
|
|
import static akka.actor.SupervisorStrategy.restart;
|
|
|
|
|
import static akka.actor.SupervisorStrategy.stop;
|
|
|
|
|
import static akka.actor.SupervisorStrategy.escalate;
|
|
|
|
|
import akka.actor.SupervisorStrategy.Directive;
|
2011-12-15 23:33:15 +01:00
|
|
|
import akka.actor.OneForOneStrategy;
|
|
|
|
|
import akka.actor.Props;
|
|
|
|
|
import akka.actor.Terminated;
|
|
|
|
|
import akka.actor.UntypedActor;
|
2012-06-29 16:06:26 +02:00
|
|
|
import scala.concurrent.Await;
|
2012-01-18 10:18:51 +01:00
|
|
|
import static akka.pattern.Patterns.ask;
|
2012-10-15 16:18:52 +02:00
|
|
|
import scala.concurrent.duration.Duration;
|
2011-12-15 23:33:15 +01:00
|
|
|
import akka.testkit.AkkaSpec;
|
|
|
|
|
import akka.testkit.TestProbe;
|
|
|
|
|
|
|
|
|
|
//#testkit
|
|
|
|
|
import akka.testkit.ErrorFilter;
|
|
|
|
|
import akka.testkit.EventFilter;
|
|
|
|
|
import akka.testkit.TestEvent;
|
2013-05-02 17:12:36 +02:00
|
|
|
import akka.testkit.JavaTestKit;
|
2011-12-15 23:33:15 +01:00
|
|
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
2012-11-07 16:35:14 +01:00
|
|
|
import static akka.japi.Util.immutableSeq;
|
2011-12-15 23:33:15 +01:00
|
|
|
import akka.japi.Function;
|
|
|
|
|
import scala.Option;
|
2012-10-30 15:08:41 +01:00
|
|
|
import scala.collection.immutable.Seq;
|
2011-12-15 23:33:15 +01:00
|
|
|
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import org.junit.BeforeClass;
|
|
|
|
|
import org.junit.AfterClass;
|
|
|
|
|
|
|
|
|
|
//#testkit
|
|
|
|
|
public class FaultHandlingTestBase {
|
|
|
|
|
//#testkit
|
2012-09-26 10:56:25 +02:00
|
|
|
static
|
2011-12-15 23:33:15 +01:00
|
|
|
//#supervisor
|
2012-09-26 10:56:25 +02:00
|
|
|
public class Supervisor extends UntypedActor {
|
2012-01-23 13:49:19 +01:00
|
|
|
|
|
|
|
|
//#strategy
|
2012-09-26 10:56:25 +02:00
|
|
|
private static SupervisorStrategy strategy =
|
2012-10-15 16:18:52 +02:00
|
|
|
new OneForOneStrategy(10, Duration.create("1 minute"),
|
2012-01-31 16:10:07 +01:00
|
|
|
new Function<Throwable, Directive>() {
|
2012-01-24 10:35:09 +01:00
|
|
|
@Override
|
2012-01-31 16:10:07 +01:00
|
|
|
public Directive apply(Throwable t) {
|
2012-01-24 10:35:09 +01:00
|
|
|
if (t instanceof ArithmeticException) {
|
|
|
|
|
return resume();
|
|
|
|
|
} else if (t instanceof NullPointerException) {
|
|
|
|
|
return restart();
|
|
|
|
|
} else if (t instanceof IllegalArgumentException) {
|
|
|
|
|
return stop();
|
|
|
|
|
} else {
|
|
|
|
|
return escalate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2012-01-23 13:49:19 +01:00
|
|
|
|
|
|
|
|
@Override
|
2012-01-23 17:18:49 +01:00
|
|
|
public SupervisorStrategy supervisorStrategy() {
|
2012-01-23 13:49:19 +01:00
|
|
|
return strategy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#strategy
|
|
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
public void onReceive(Object o) {
|
|
|
|
|
if (o instanceof Props) {
|
2012-09-19 23:55:53 +02:00
|
|
|
getSender().tell(getContext().actorOf((Props) o), getSelf());
|
2011-12-29 20:49:26 +01:00
|
|
|
} else {
|
|
|
|
|
unhandled(o);
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#supervisor
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2012-09-26 10:56:25 +02:00
|
|
|
static
|
2011-12-15 23:33:15 +01:00
|
|
|
//#supervisor2
|
2012-09-26 10:56:25 +02:00
|
|
|
public class Supervisor2 extends UntypedActor {
|
2012-01-23 13:49:19 +01:00
|
|
|
|
|
|
|
|
//#strategy2
|
2012-09-26 10:56:25 +02:00
|
|
|
private static SupervisorStrategy strategy = new OneForOneStrategy(10,
|
2012-10-15 16:18:52 +02:00
|
|
|
Duration.create("1 minute"),
|
2012-01-31 16:10:07 +01:00
|
|
|
new Function<Throwable, Directive>() {
|
2012-01-24 10:35:09 +01:00
|
|
|
@Override
|
2012-01-31 16:10:07 +01:00
|
|
|
public Directive apply(Throwable t) {
|
2012-01-24 10:35:09 +01:00
|
|
|
if (t instanceof ArithmeticException) {
|
|
|
|
|
return resume();
|
|
|
|
|
} else if (t instanceof NullPointerException) {
|
|
|
|
|
return restart();
|
|
|
|
|
} else if (t instanceof IllegalArgumentException) {
|
|
|
|
|
return stop();
|
|
|
|
|
} else {
|
|
|
|
|
return escalate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2012-01-23 13:49:19 +01:00
|
|
|
|
|
|
|
|
@Override
|
2012-01-23 17:18:49 +01:00
|
|
|
public SupervisorStrategy supervisorStrategy() {
|
2012-01-23 13:49:19 +01:00
|
|
|
return strategy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#strategy2
|
|
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
public void onReceive(Object o) {
|
|
|
|
|
if (o instanceof Props) {
|
2012-09-19 23:55:53 +02:00
|
|
|
getSender().tell(getContext().actorOf((Props) o), getSelf());
|
2011-12-29 20:49:26 +01:00
|
|
|
} else {
|
|
|
|
|
unhandled(o);
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
@Override
|
|
|
|
|
public void preRestart(Throwable cause, Option<Object> msg) {
|
|
|
|
|
// do not kill all children, which is the default here
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#supervisor2
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2012-09-26 10:56:25 +02:00
|
|
|
static
|
2011-12-15 23:33:15 +01:00
|
|
|
//#child
|
2012-09-26 10:56:25 +02:00
|
|
|
public class Child extends UntypedActor {
|
2011-12-15 23:33:15 +01:00
|
|
|
int state = 0;
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
public void onReceive(Object o) throws Exception {
|
|
|
|
|
if (o instanceof Exception) {
|
|
|
|
|
throw (Exception) o;
|
|
|
|
|
} else if (o instanceof Integer) {
|
|
|
|
|
state = (Integer) o;
|
|
|
|
|
} else if (o.equals("get")) {
|
2012-09-19 23:55:53 +02:00
|
|
|
getSender().tell(state, getSelf());
|
2011-12-29 20:49:26 +01:00
|
|
|
} else {
|
|
|
|
|
unhandled(o);
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#child
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#testkit
|
|
|
|
|
static ActorSystem system;
|
|
|
|
|
Duration timeout = Duration.create(5, SECONDS);
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
@BeforeClass
|
|
|
|
|
public static void start() {
|
|
|
|
|
system = ActorSystem.create("test", AkkaSpec.testConf());
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
@AfterClass
|
|
|
|
|
public static void cleanup() {
|
2013-05-02 17:12:36 +02:00
|
|
|
JavaTestKit.shutdownActorSystem(system);
|
|
|
|
|
system = null;
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
@Test
|
2012-02-16 12:31:49 +01:00
|
|
|
public void mustEmploySupervisorStrategy() throws Exception {
|
2011-12-15 23:33:15 +01:00
|
|
|
// code here
|
|
|
|
|
//#testkit
|
|
|
|
|
EventFilter ex1 = (EventFilter) new ErrorFilter(ArithmeticException.class);
|
|
|
|
|
EventFilter ex2 = (EventFilter) new ErrorFilter(NullPointerException.class);
|
|
|
|
|
EventFilter ex3 = (EventFilter) new ErrorFilter(IllegalArgumentException.class);
|
|
|
|
|
EventFilter ex4 = (EventFilter) new ErrorFilter(Exception.class);
|
|
|
|
|
Seq<EventFilter> ignoreExceptions = seq(ex1, ex2, ex3, ex4);
|
|
|
|
|
system.eventStream().publish(new TestEvent.Mute(ignoreExceptions));
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#create
|
2013-04-14 22:56:41 +02:00
|
|
|
Props superprops = Props.create(Supervisor.class);
|
2011-12-15 23:33:15 +01:00
|
|
|
ActorRef supervisor = system.actorOf(superprops, "supervisor");
|
2012-09-26 10:56:25 +02:00
|
|
|
ActorRef child = (ActorRef) Await.result(ask(supervisor,
|
2013-04-14 22:56:41 +02:00
|
|
|
Props.create(Child.class), 5000), timeout);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#create
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#resume
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(42, null);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(new ArithmeticException(), null);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#resume
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#restart
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(new NullPointerException(), null);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#restart
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#stop
|
|
|
|
|
final TestProbe probe = new TestProbe(system);
|
|
|
|
|
probe.watch(child);
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(new IllegalArgumentException(), null);
|
2012-08-20 11:22:52 +02:00
|
|
|
probe.expectMsgClass(Terminated.class);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#stop
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#escalate-kill
|
2012-09-26 10:56:25 +02:00
|
|
|
child = (ActorRef) Await.result(ask(supervisor,
|
2013-04-14 22:56:41 +02:00
|
|
|
Props.create(Child.class), 5000), timeout);
|
2011-12-15 23:33:15 +01:00
|
|
|
probe.watch(child);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(new Exception(), null);
|
2012-08-20 11:22:52 +02:00
|
|
|
probe.expectMsgClass(Terminated.class);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#escalate-kill
|
2012-01-23 13:49:19 +01:00
|
|
|
|
2011-12-15 23:33:15 +01:00
|
|
|
//#escalate-restart
|
2013-04-14 22:56:41 +02:00
|
|
|
superprops = Props.create(Supervisor2.class);
|
2012-07-24 14:26:22 +02:00
|
|
|
supervisor = system.actorOf(superprops);
|
2012-09-26 10:56:25 +02:00
|
|
|
child = (ActorRef) Await.result(ask(supervisor,
|
2013-04-14 22:56:41 +02:00
|
|
|
Props.create(Child.class), 5000), timeout);
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(23, null);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(23);
|
2012-09-19 23:55:53 +02:00
|
|
|
child.tell(new Exception(), null);
|
2011-12-17 17:18:50 -08:00
|
|
|
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
|
2011-12-15 23:33:15 +01:00
|
|
|
//#escalate-restart
|
|
|
|
|
//#testkit
|
|
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
|
|
|
|
|
//#testkit
|
2013-04-14 22:56:41 +02:00
|
|
|
@SuppressWarnings("unchecked")
|
2011-12-15 23:33:15 +01:00
|
|
|
public <A> Seq<A> seq(A... args) {
|
2012-11-07 16:35:14 +01:00
|
|
|
return immutableSeq(args);
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
2012-01-23 13:49:19 +01:00
|
|
|
//#testkit
|
2011-12-15 23:33:15 +01:00
|
|
|
}
|
2012-08-22 16:44:35 +02:00
|
|
|
//#testkit
|