The idea is to filter the sources, replacing @<var>@ occurrences with the mapping for <var> (which is currently hard-coded). @@ -> @. In order to make this work, I had to move the doc sources one directory down (into akka-docs/rst) so that the filtered result could be in a sibling directory so that relative links (to _sphinx plugins or real code) would continue to work. While I was at it I also changed it so that WARNINGs and ERRORs are not swallowed into the debug dump anymore but printed at [warn] level (minimum). One piece of fallout is that the (online) html build is now run after the normal one, not in parallel.
156 lines
4.1 KiB
Scala
156 lines
4.1 KiB
Scala
/**
|
||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||
*/
|
||
package docs.actor
|
||
|
||
import language.postfixOps
|
||
|
||
//#testkit
|
||
import akka.testkit.{ AkkaSpec, ImplicitSender, EventFilter }
|
||
import akka.actor.{ ActorRef, Props, Terminated }
|
||
|
||
//#testkit
|
||
object FaultHandlingDocSpec {
|
||
//#supervisor
|
||
//#child
|
||
import akka.actor.Actor
|
||
|
||
//#child
|
||
//#supervisor
|
||
//#supervisor
|
||
class Supervisor extends Actor {
|
||
//#strategy
|
||
import akka.actor.OneForOneStrategy
|
||
import akka.actor.SupervisorStrategy._
|
||
import scala.concurrent.util.duration._
|
||
|
||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
|
||
case _: ArithmeticException ⇒ Resume
|
||
case _: NullPointerException ⇒ Restart
|
||
case _: IllegalArgumentException ⇒ Stop
|
||
case _: Exception ⇒ Escalate
|
||
}
|
||
//#strategy
|
||
|
||
def receive = {
|
||
case p: Props ⇒ sender ! context.actorOf(p)
|
||
}
|
||
}
|
||
//#supervisor
|
||
|
||
//#supervisor2
|
||
class Supervisor2 extends Actor {
|
||
//#strategy2
|
||
import akka.actor.OneForOneStrategy
|
||
import akka.actor.SupervisorStrategy._
|
||
import scala.concurrent.util.duration._
|
||
|
||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
|
||
case _: ArithmeticException ⇒ Resume
|
||
case _: NullPointerException ⇒ Restart
|
||
case _: IllegalArgumentException ⇒ Stop
|
||
case _: Exception ⇒ Escalate
|
||
}
|
||
//#strategy2
|
||
|
||
def receive = {
|
||
case p: Props ⇒ sender ! context.actorOf(p)
|
||
}
|
||
// override default to kill all children during restart
|
||
override def preRestart(cause: Throwable, msg: Option[Any]) {}
|
||
}
|
||
//#supervisor2
|
||
|
||
//#child
|
||
class Child extends Actor {
|
||
var state = 0
|
||
def receive = {
|
||
case ex: Exception ⇒ throw ex
|
||
case x: Int ⇒ state = x
|
||
case "get" ⇒ sender ! state
|
||
}
|
||
}
|
||
//#child
|
||
}
|
||
|
||
//#testkit
|
||
class FaultHandlingDocSpec extends AkkaSpec with ImplicitSender {
|
||
//#testkit
|
||
|
||
import FaultHandlingDocSpec._
|
||
//#testkit
|
||
|
||
"A supervisor" must {
|
||
|
||
"apply the chosen strategy for its child" in {
|
||
//#testkit
|
||
|
||
//#create
|
||
val supervisor = system.actorOf(Props[Supervisor], "supervisor")
|
||
|
||
supervisor ! Props[Child]
|
||
val child = expectMsgType[ActorRef] // retrieve answer from TestKit’s testActor
|
||
//#create
|
||
EventFilter[ArithmeticException](occurrences = 1) intercept {
|
||
//#resume
|
||
child ! 42 // set state to 42
|
||
child ! "get"
|
||
expectMsg(42)
|
||
|
||
child ! new ArithmeticException // crash it
|
||
child ! "get"
|
||
expectMsg(42)
|
||
//#resume
|
||
}
|
||
EventFilter[NullPointerException](occurrences = 1) intercept {
|
||
//#restart
|
||
child ! new NullPointerException // crash it harder
|
||
child ! "get"
|
||
expectMsg(0)
|
||
//#restart
|
||
}
|
||
EventFilter[IllegalArgumentException](occurrences = 1) intercept {
|
||
//#stop
|
||
watch(child) // have testActor watch “child”
|
||
child ! new IllegalArgumentException // break it
|
||
expectMsgPF() {
|
||
case t @ Terminated(`child`) if t.existenceConfirmed ⇒ ()
|
||
}
|
||
child.isTerminated must be(true)
|
||
//#stop
|
||
}
|
||
EventFilter[Exception]("CRASH", occurrences = 4) intercept {
|
||
//#escalate-kill
|
||
supervisor ! Props[Child] // create new child
|
||
val child2 = expectMsgType[ActorRef]
|
||
|
||
watch(child2)
|
||
child2 ! "get" // verify it is alive
|
||
expectMsg(0)
|
||
|
||
child2 ! new Exception("CRASH") // escalate failure
|
||
expectMsgPF() {
|
||
case t @ Terminated(`child2`) if t.existenceConfirmed ⇒ ()
|
||
}
|
||
//#escalate-kill
|
||
//#escalate-restart
|
||
val supervisor2 = system.actorOf(Props[Supervisor2], "supervisor2")
|
||
|
||
supervisor2 ! Props[Child]
|
||
val child3 = expectMsgType[ActorRef]
|
||
|
||
child3 ! 23
|
||
child3 ! "get"
|
||
expectMsg(23)
|
||
|
||
child3 ! new Exception("CRASH")
|
||
child3 ! "get"
|
||
expectMsg(0)
|
||
//#escalate-restart
|
||
}
|
||
//#testkit
|
||
// code here
|
||
}
|
||
}
|
||
}
|
||
//#testkit
|