#22687 Undefer before terminate
This commit is contained in:
parent
70d8c42b05
commit
124c374a5f
3 changed files with 15 additions and 28 deletions
|
|
@ -155,13 +155,9 @@ object Behavior {
|
|||
}
|
||||
|
||||
@tailrec
|
||||
def undefer[T](deferredBehavior: DeferredBehavior[T], ctx: ActorContext[T]): Behavior[T] = {
|
||||
val behavior = deferredBehavior(ctx)
|
||||
|
||||
behavior match {
|
||||
case innerDeferred: DeferredBehavior[T] @unchecked ⇒ undefer(innerDeferred, ctx)
|
||||
case _ ⇒ behavior
|
||||
}
|
||||
def undefer[T](behavior: Behavior[T], ctx: ActorContext[T]): Behavior[T] = behavior match {
|
||||
case innerDeferred: DeferredBehavior[T] @unchecked ⇒ undefer(innerDeferred(ctx), ctx)
|
||||
case _ ⇒ behavior
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,7 +165,7 @@ object Behavior {
|
|||
* notably the behavior can neither be `Same` nor `Unhandled`. Starting
|
||||
* out with a `Stopped` behavior is allowed, though.
|
||||
*/
|
||||
def validateAsInitial[T](behavior: Behavior[T]): Behavior[T] =
|
||||
def validateAsInitial[T](behavior: BehaSo I get updates every day or so. Bleeding edge, but also works whenever I need it, which is quite rare as well. vior[T]): Behavior[T] =
|
||||
behavior match {
|
||||
case SameBehavior | UnhandledBehavior ⇒
|
||||
throw new IllegalArgumentException(s"cannot use $behavior as initial behavior")
|
||||
|
|
@ -179,12 +175,8 @@ object Behavior {
|
|||
/**
|
||||
* Validate the given behavior as initial, initialize it if it is deferred.
|
||||
*/
|
||||
def preStart[T](behavior: Behavior[T], ctx: ActorContext[T]): Behavior[T] = {
|
||||
validateAsInitial(behavior) match {
|
||||
case d: DeferredBehavior[T] @unchecked ⇒ validateAsInitial(undefer(d, ctx))
|
||||
case x ⇒ x
|
||||
}
|
||||
}
|
||||
def preStart[T](behavior: Behavior[T], ctx: ActorContext[T]): Behavior[T] =
|
||||
validateAsInitial(undefer(behavior, ctx))
|
||||
|
||||
/**
|
||||
* Returns true if the given behavior is not stopped.
|
||||
|
|
@ -210,8 +202,8 @@ object Behavior {
|
|||
|
||||
private def interpret[T](behavior: Behavior[T], ctx: ActorContext[T], msg: Any): Behavior[T] =
|
||||
behavior match {
|
||||
case SameBehavior | UnhandledBehavior ⇒ throw new IllegalArgumentException(s"cannot execute with $behavior as behavior")
|
||||
case _: DeferredBehavior[_] ⇒ throw new IllegalArgumentException(s"deferred should not be passed to interpreter")
|
||||
case SameBehavior | UnhandledBehavior ⇒ throw new IllegalArgumentException(s"cannot execute with [$behavior] as behavior")
|
||||
case d: DeferredBehavior[_] ⇒ throw new IllegalArgumentException(s"deferred [$d] should not be passed to interpreter")
|
||||
case IgnoreBehavior ⇒ SameBehavior.asInstanceOf[Behavior[T]]
|
||||
case StoppedBehavior ⇒ StoppedBehavior.asInstanceOf[Behavior[T]]
|
||||
case EmptyBehavior ⇒ UnhandledBehavior.asInstanceOf[Behavior[T]]
|
||||
|
|
@ -220,10 +212,7 @@ object Behavior {
|
|||
case signal: Signal ⇒ ext.management(ctx, signal)
|
||||
case msg ⇒ ext.message(ctx, msg.asInstanceOf[T])
|
||||
}
|
||||
possiblyDeferredResult match {
|
||||
case d: DeferredBehavior[T] @unchecked ⇒ undefer(d, ctx)
|
||||
case notDeferred ⇒ notDeferred
|
||||
}
|
||||
undefer(possiblyDeferredResult, ctx)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
package akka.typed
|
||||
package internal
|
||||
|
||||
import scala.annotation.{ switch, tailrec }
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.control.Exception.Catcher
|
||||
import akka.event.Logging
|
||||
import akka.typed.Behavior.DeferredBehavior
|
||||
|
||||
|
|
@ -89,8 +87,10 @@ private[typed] trait SupervisionMechanics[T] {
|
|||
val a = behavior
|
||||
/*
|
||||
* The following order is crucial for things to work properly. Only change this if you're very confident and lucky.
|
||||
*
|
||||
* Do not undefer a DeferredBehavior as that may cause creation side-effects, which we do not want on termination.
|
||||
*/
|
||||
try if (a ne null) Behavior.canonicalize(Behavior.interpretSignal(a, ctx, PostStop), a, ctx)
|
||||
try if ((a ne null) && !a.isInstanceOf[DeferredBehavior[_]]) Behavior.canonicalize(Behavior.interpretSignal(a, ctx, PostStop), a, ctx)
|
||||
catch { case NonFatal(ex) ⇒ publish(Logging.Error(ex, self.path.toString, clazz(a), "failure during PostStop")) }
|
||||
finally try tellWatchersWeDied()
|
||||
finally try parent.sendSystem(DeathWatchNotification(self, failed))
|
||||
|
|
|
|||
|
|
@ -32,15 +32,13 @@ final case class Restarter[T, Thr <: Throwable: ClassTag](initialBehavior: Behav
|
|||
else if (b eq behavior) Same
|
||||
else {
|
||||
b match {
|
||||
case d: DeferredBehavior[_] ⇒ canonical(Behavior.undefer(d.asInstanceOf[DeferredBehavior[T]], ctx), ctx)
|
||||
case d: DeferredBehavior[_] ⇒ canonical(Behavior.undefer(d, ctx), ctx)
|
||||
case b ⇒ Restarter[T, Thr](initialBehavior, resume)(b)
|
||||
}
|
||||
}
|
||||
|
||||
private def preStart(b: Behavior[T], ctx: ActorContext[T]): Behavior[T] = b match {
|
||||
case d: DeferredBehavior[_] ⇒ Behavior.undefer(d.asInstanceOf[DeferredBehavior[T]], ctx)
|
||||
case b ⇒ b
|
||||
}
|
||||
private def preStart(b: Behavior[T], ctx: ActorContext[T]): Behavior[T] =
|
||||
Behavior.undefer(b, ctx)
|
||||
|
||||
override def management(ctx: ActorContext[T], signal: Signal): Behavior[T] = {
|
||||
val startedBehavior = preStart(behavior, ctx)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue