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")
|
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
|
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 =
|
final protected def writeObject(o: ObjectOutputStream): Unit =
|
||||||
throw new NotSerializableException("ActorContext is not serializable!")
|
throw new NotSerializableException("ActorContext is not serializable!")
|
||||||
}
|
}
|
||||||
|
|
@ -417,11 +409,6 @@ private[akka] class ActorCell(
|
||||||
subject
|
subject
|
||||||
}
|
}
|
||||||
|
|
||||||
final def suspendForChildTermination(): Unit = childrenRefs match {
|
|
||||||
case _: TerminatingChildrenContainer ⇒ dispatcher suspend this
|
|
||||||
case _ ⇒
|
|
||||||
}
|
|
||||||
|
|
||||||
final def children: Iterable[ActorRef] = childrenRefs.children
|
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))
|
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
|
// prevent any further messages to be processed until the actor has been restarted
|
||||||
dispatcher.suspend(this)
|
dispatcher.suspend(this)
|
||||||
|
actor.supervisorStrategy.handleSupervisorFailing(self, children)
|
||||||
} finally {
|
} finally {
|
||||||
parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self)
|
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))
|
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 {
|
childrenRefs match {
|
||||||
case tc @ TerminatingChildrenContainer(_, _, reason) ⇒
|
case tc @ TerminatingChildrenContainer(_, _, reason) ⇒
|
||||||
val n = tc.remove(child)
|
val n = tc.remove(child)
|
||||||
childrenRefs = n
|
childrenRefs = n
|
||||||
actor.supervisorStrategy.handleChildTerminated(this, child, children)
|
actor.supervisorStrategy.handleChildTerminated(this, child, children)
|
||||||
if (!n.isInstanceOf[TerminatingChildrenContainer]) reason match {
|
if (!n.isInstanceOf[TerminatingChildrenContainer]) reason match {
|
||||||
case UserRequest ⇒ if (mailbox.isSuspended) dispatcher resume this
|
|
||||||
case Recreation(cause) ⇒ doRecreate(cause)
|
case Recreation(cause) ⇒ doRecreate(cause)
|
||||||
case Termination ⇒ doTerminate()
|
case Termination ⇒ doTerminate()
|
||||||
|
case _ ⇒
|
||||||
}
|
}
|
||||||
case _ ⇒
|
case _ ⇒
|
||||||
childrenRefs = childrenRefs.remove(child)
|
childrenRefs = childrenRefs.remove(child)
|
||||||
actor.supervisorStrategy.handleChildTerminated(this, child, children)
|
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 ⬅⬅⬅
|
// ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅
|
||||||
|
|
|
||||||
|
|
@ -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
|
and therefore not receiving the stop command), this whole process will be
|
||||||
stuck.
|
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
|
Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be
|
||||||
stopped, and the aforementioned process will ensure proper termination of the
|
stopped, and the aforementioned process will ensure proper termination of the
|
||||||
whole system.
|
whole system.
|
||||||
|
|
@ -478,6 +467,13 @@ enables cleaning up of resources:
|
||||||
// close some file or database connection
|
// 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
|
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
|
and therefore not receiving the stop command), this whole process will be
|
||||||
stuck.
|
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
|
Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be
|
||||||
stopped, and the aforementioned process will ensure proper termination of the
|
stopped, and the aforementioned process will ensure proper termination of the
|
||||||
whole system.
|
whole system.
|
||||||
|
|
@ -526,6 +515,13 @@ enables cleaning up of resources:
|
||||||
// close some file or database connection
|
// 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
|
PoisonPill
|
||||||
----------
|
----------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue