remove ActorContext.suspendForChildTermination, handle exceptions, add docs
This commit is contained in:
parent
4cea8ee83e
commit
37284bab4f
5 changed files with 31 additions and 55 deletions
|
|
@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ⬅⬅⬅
|
||||
|
|
|
|||
|
|
@ -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``.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
----------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
----------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue