remove ActorContext.suspendForChildTermination, handle exceptions, add docs

This commit is contained in:
Roland 2012-03-01 17:36:05 +01:00
parent 4cea8ee83e
commit 37284bab4f
5 changed files with 31 additions and 55 deletions

View file

@ -142,17 +142,5 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
expectMsg("green")
}
"support suspending until all dying children have properly expired" in {
val parent = system.actorOf(Props(new Actor {
val child = context.actorOf(Props.empty, "bob")
def receive = {
case "engage" context.stop(child); context.suspendForChildTermination(); self ! "next"
case "next" context.actorOf(Props.empty, "bob"); testActor ! "green"
}
}))
parent ! "engage"
expectMsg("green")
}
}
}

View file

@ -134,14 +134,6 @@ trait ActorContext extends ActorRefFactory {
*/
def unwatch(subject: ActorRef): ActorRef
/**
* Suspend this actor (after finishing processing of the current message)
* until all children for which stop(child) has been called have actually
* terminated. This is useful if a new child with the same name needs to
* be created before processing can continue.
*/
def suspendForChildTermination(): Unit
final protected def writeObject(o: ObjectOutputStream): Unit =
throw new NotSerializableException("ActorContext is not serializable!")
}
@ -417,11 +409,6 @@ private[akka] class ActorCell(
subject
}
final def suspendForChildTermination(): Unit = childrenRefs match {
case _: TerminatingChildrenContainer dispatcher suspend this
case _
}
final def children: Iterable[ActorRef] = childrenRefs.children
/**
@ -686,6 +673,7 @@ private[akka] class ActorCell(
dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e))
// prevent any further messages to be processed until the actor has been restarted
dispatcher.suspend(this)
actor.supervisorStrategy.handleSupervisorFailing(self, children)
} finally {
parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self)
}
@ -696,21 +684,29 @@ private[akka] class ActorCell(
case None system.eventStream.publish(Warning(self.path.toString, clazz(actor), "dropping Failed(" + cause + ") from unknown child " + child))
}
final def handleChildTerminated(child: ActorRef): Unit = {
final def handleChildTerminated(child: ActorRef): Unit = try {
childrenRefs match {
case tc @ TerminatingChildrenContainer(_, _, reason)
val n = tc.remove(child)
childrenRefs = n
actor.supervisorStrategy.handleChildTerminated(this, child, children)
if (!n.isInstanceOf[TerminatingChildrenContainer]) reason match {
case UserRequest if (mailbox.isSuspended) dispatcher resume this
case Recreation(cause) doRecreate(cause)
case Termination doTerminate()
case _
}
case _
childrenRefs = childrenRefs.remove(child)
actor.supervisorStrategy.handleChildTerminated(this, child, children)
}
} catch {
case NonFatal(e)
try {
dispatcher suspend this
actor.supervisorStrategy.handleSupervisorFailing(self, children)
} finally {
parent.tell(Failed(e), self)
}
}
// ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅

View file

@ -179,10 +179,10 @@ By having your Typed Actor implementation class implement any and all of the fol
* ``TypedActor.PreRestart``
* ``TypedActor.PostRestart``
You can hook into the lifecycle of your Typed Actor.
You can hook into the lifecycle of your Typed Actor.
Proxying
--------
Proxying
--------
You can use the ``typedActorOf`` that takes a TypedProps and an ActorRef to proxy the given ActorRef as a TypedActor.
This is usable if you want to communicate remotely with TypedActors on other machines, just look them up with ``actorFor`` and pass the ``ActorRef`` to ``typedActorOf``.
You can use the ``typedActorOf`` that takes a TypedProps and an ActorRef to proxy the given ActorRef as a TypedActor.
This is usable if you want to communicate remotely with TypedActors on other machines, just look them up with ``actorFor`` and pass the ``ActorRef`` to ``typedActorOf``.

View file

@ -453,17 +453,6 @@ actors does not respond (i.e. processing a message for extended periods of time
and therefore not receiving the stop command), this whole process will be
stuck.
It is possible to disregard specific children with respect to shutdown
confirmation by stopping them explicitly before issuing the
``context.stop(self)``::
context.stop(someChild);
context.stop(self);
In this case ``someChild`` will be stopped asynchronously and re-parented to
the :class:`Locker`, where :class:`DavyJones` will keep tabs and dispose of it
eventually.
Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be
stopped, and the aforementioned process will ensure proper termination of the
whole system.
@ -478,6 +467,13 @@ enables cleaning up of resources:
// close some file or database connection
}
.. note::
Since stopping an actor is asynchronous, you cannot immediately reuse the
name of the child you just stopped; this will result in an
:class:`InvalidActorNameException`. Instead, :meth:`watch()` the terminating
actor and create its replacement in response to the :class:`Terminated`
message which will eventually arrive.
PoisonPill
----------

View file

@ -502,17 +502,6 @@ actors does not respond (i.e. processing a message for extended periods of time
and therefore not receiving the stop command), this whole process will be
stuck.
It is possible to disregard specific children with respect to shutdown
confirmation by stopping them explicitly before issuing the
``context.stop(self)``::
context.stop(someChild)
context.stop(self)
In this case ``someChild`` will be stopped asynchronously and re-parented to
the :class:`Locker`, where :class:`DavyJones` will keep tabs and dispose of it
eventually.
Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be
stopped, and the aforementioned process will ensure proper termination of the
whole system.
@ -526,6 +515,13 @@ enables cleaning up of resources:
// close some file or database connection
}
.. note::
Since stopping an actor is asynchronous, you cannot immediately reuse the
name of the child you just stopped; this will result in an
:class:`InvalidActorNameException`. Instead, :meth:`watch()` the terminating
actor and create its replacement in response to the :class:`Terminated`
message which will eventually arrive.
PoisonPill
----------