From 25a6342c8536d9628f722d8ff4ac2eeab9fdb2ce Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Fri, 5 Jul 2024 09:49:29 +0800 Subject: [PATCH 1/8] feat: support the flattening syntax for supervising --- .../actor/typed/javadsl/ActorCompile.java | 5 +- .../java/jdocs/akka/typed/RouterTest.java | 2 +- .../SupervisionCompileOnlyTest.java | 6 +-- .../akka/actor/typed/SupervisionSpec.scala | 6 +-- .../supervision/SupervisionCompileOnly.scala | 3 +- .../scala/akka/actor/typed/Behavior.scala | 46 ++++++++++++++++++- .../actor/typed/internal/BehaviorImpl.scala | 1 + .../akka/actor/typed/javadsl/Behaviors.scala | 23 +--------- .../akka/actor/typed/scaladsl/Behaviors.scala | 15 +----- .../tutorial_1/ActorHierarchyExperiments.java | 2 +- 10 files changed, 61 insertions(+), 48 deletions(-) diff --git a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java index 2c8634ca017..e48cefb0f4a 100644 --- a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java +++ b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java @@ -173,9 +173,8 @@ public Behavior receive(TypedActorContext context, MyMsg message) SupervisorStrategy strategy7 = strategy6.withResetBackoffAfter(Duration.ofSeconds(2)); Behavior behv = - Behaviors.supervise( - Behaviors.supervise(Behaviors.ignore()) - .onFailure(IllegalStateException.class, strategy6)) + Behaviors.supervise(Behaviors.ignore()) + .onFailure(IllegalStateException.class, strategy6) .onFailure(RuntimeException.class, strategy1); } diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java index 360751660bd..ccce159867d 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java @@ -124,7 +124,7 @@ static Behavior showPoolRouting() { Routers.pool( poolSize, // make sure the workers are restarted if they fail - Behaviors.supervise(Worker.create()).onFailure(SupervisorStrategy.restart())); + Behaviors.supervise(Worker.create()).onAnyFailure(SupervisorStrategy.restart())); ActorRef router = context.spawn(pool, "worker-pool"); for (int i = 0; i < 10; i++) { diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java index 2df4265eb09..64876805fac 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java @@ -33,7 +33,7 @@ public Got(int n) { // #top-level public static Behavior create() { - return Behaviors.supervise(counter(1)).onFailure(SupervisorStrategy.restart()); + return Behaviors.supervise(counter(1)).onAnyFailure(SupervisorStrategy.restart()); } // #top-level @@ -105,7 +105,7 @@ static Behavior parent() { return Behaviors.same(); }); })) - .onFailure(SupervisorStrategy.restart()); + .onAnyFailure(SupervisorStrategy.restart()); } // #restart-stop-children @@ -126,7 +126,7 @@ static Behavior parent2() { child2.tell(parts[1]); return Behaviors.same(); })) - .onFailure(SupervisorStrategy.restart().withStopChildren(false)); + .onAnyFailure(SupervisorStrategy.restart().withStopChildren(false)); }); } // #restart-keep-children diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala index 33f93560868..61c388a5401 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala @@ -166,9 +166,9 @@ class StubbedSupervisionSpec extends AnyWordSpec with Matchers with LogCapturing "support nesting to handle different exceptions" in { val inbox = TestInbox[Event]("evt") - val behv = - supervise(supervise(targetBehavior(inbox.ref)).onFailure[Exc2](SupervisorStrategy.resume)) - .onFailure[Exc3](SupervisorStrategy.restart) + val behv = supervise(targetBehavior(inbox.ref)) + .onFailure[Exc2](SupervisorStrategy.resume) + .onFailure[Exc3](SupervisorStrategy.restart) val testkit = BehaviorTestKit(behv) testkit.run(IncrementState) testkit.run(GetState) diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala index 54341c5f2d0..563e34b2859 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala @@ -34,7 +34,8 @@ object SupervisionCompileOnly { //#multiple Behaviors - .supervise(Behaviors.supervise(behavior).onFailure[IllegalStateException](SupervisorStrategy.restart)) + .supervise(behavior) + .onFailure[IllegalStateException](SupervisorStrategy.restart) .onFailure[IllegalArgumentException](SupervisorStrategy.stop) //#multiple diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala index 6ed9db91a19..7aa958edce3 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala @@ -7,7 +7,6 @@ package akka.actor.typed import scala.annotation.switch import scala.annotation.tailrec import scala.reflect.ClassTag - import akka.actor.InvalidMessageException import akka.actor.typed.internal.BehaviorImpl import akka.actor.typed.internal.BehaviorImpl.DeferredBehavior @@ -15,6 +14,7 @@ import akka.actor.typed.internal.BehaviorImpl.StoppedBehavior import akka.actor.typed.internal.BehaviorTags import akka.actor.typed.internal.CachedProps import akka.actor.typed.internal.InterceptorImpl +import akka.actor.typed.internal.Supervisor import akka.annotation.DoNotInherit import akka.annotation.InternalApi import akka.util.OptionVal @@ -113,6 +113,45 @@ abstract class ExtensibleBehavior[T] extends Behavior[T](BehaviorTags.Extensible def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] } +/** + * INTERNAL API + * A behavior type that could be supervised, Not for user extension. + */ +@InternalApi +final class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) + extends Behavior[T](BehaviorTags.SuperviseBehavior) { + private final val ThrowableClassTag = ClassTag(classOf[Throwable]) + + /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ + def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)( + implicit tag: ClassTag[Thr] = ThrowableClassTag): SuperviseBehavior[T] = { + val effectiveTag = if (tag == ClassTag.Nothing) ThrowableClassTag else tag + new SuperviseBehavior[T](Supervisor(Behavior.validateAsInitial(wrapped), strategy)(effectiveTag)) + } + + /** + * Java API: + * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. + * + * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. + */ + def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = { + onFailure(strategy)(ClassTag(clazz)) + } + + /** + * Java API: + * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. + * + * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. + */ + def onAnyFailure[Thr <: Throwable](strategy: SupervisorStrategy): SuperviseBehavior[T] = { + onFailure(classOf[Exception], strategy) + } + + private[akka] def unwrap: Behavior[T] = wrapped +} + object Behavior { final implicit class BehaviorDecorators[Inner](val behavior: Behavior[Inner]) extends AnyVal { @@ -179,7 +218,8 @@ object Behavior { val startedInner = start(wrapped.nestedBehavior, ctx.asInstanceOf[TypedActorContext[Any]]) if (startedInner eq wrapped.nestedBehavior) wrapped else wrapped.replaceNested(startedInner) - case _ => behavior + case supervise: SuperviseBehavior[T] => start(supervise.unwrap, ctx) + case _ => behavior } } @@ -265,6 +305,8 @@ object Behavior { throw new IllegalArgumentException(s"cannot execute with [$behavior] as behavior") case BehaviorTags.DeferredBehavior => throw new IllegalArgumentException(s"deferred [$behavior] should not be passed to interpreter") + case BehaviorTags.SuperviseBehavior => + throw new IllegalArgumentException(s"supervise [$behavior] should not be passed to interpreter") case BehaviorTags.IgnoreBehavior => BehaviorImpl.same[T] case BehaviorTags.StoppedBehavior => diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/BehaviorImpl.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/BehaviorImpl.scala index c848ec344d6..eb207c1d85b 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/BehaviorImpl.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/BehaviorImpl.scala @@ -29,6 +29,7 @@ private[akka] object BehaviorTags { final val SameBehavior = 6 final val FailedBehavior = 7 final val StoppedBehavior = 8 + final val SuperviseBehavior = 9 } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala index 91d7f99ed88..5d77a5bf95c 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala @@ -250,27 +250,8 @@ object Behaviors { * .onFailure[IndexOutOfBoundsException](SupervisorStrategy.resume) // resume for IndexOutOfBoundsException exceptions * }}} */ - def supervise[T](wrapped: Behavior[T]): Supervise[T] = - new Supervise[T](wrapped) - - final class Supervise[T] private[akka] (wrapped: Behavior[T]) { - - /** - * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. - * - * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. - */ - def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): Behavior[T] = - Supervisor(Behavior.validateAsInitial(wrapped), strategy)(ClassTag(clazz)) - - /** - * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. - * - * All non-fatal (see [[scala.util.control.NonFatal]]) exceptions types will be handled using the given strategy. - */ - def onFailure(strategy: SupervisorStrategy): Behavior[T] = - onFailure(classOf[Exception], strategy) - } + def supervise[T](wrapped: Behavior[T]): SuperviseBehavior[T] = + scaladsl.Behaviors.supervise(wrapped) /** * Transform the incoming messages by placing a funnel in front of the wrapped `Behavior`: the supplied diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala index 4145fb02046..9092cef195f 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala @@ -215,19 +215,8 @@ object Behaviors { * .onFailure[IndexOutOfBoundsException](SupervisorStrategy.resume) // resume for IndexOutOfBoundsException exceptions * }}} */ - def supervise[T](wrapped: Behavior[T]): Supervise[T] = - new Supervise[T](wrapped) - - private final val ThrowableClassTag = ClassTag(classOf[Throwable]) - final class Supervise[T] private[akka] (val wrapped: Behavior[T]) extends AnyVal { - - /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ - def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)( - implicit tag: ClassTag[Thr] = ThrowableClassTag): Behavior[T] = { - val effectiveTag = if (tag == ClassTag.Nothing) ThrowableClassTag else tag - Supervisor(Behavior.validateAsInitial(wrapped), strategy)(effectiveTag) - } - } + def supervise[T](wrapped: Behavior[T]): SuperviseBehavior[T] = + new SuperviseBehavior[T](wrapped) /** * Support for scheduled `self` messages in an actor. diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java index 3681f6c094d..5292b3f5419 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java @@ -111,7 +111,7 @@ private SupervisingActor(ActorContext context) { super(context); child = context.spawn( - Behaviors.supervise(SupervisedActor.create()).onFailure(SupervisorStrategy.restart()), + Behaviors.supervise(SupervisedActor.create()).onAnyFailure(SupervisorStrategy.restart()), "supervised-actor"); } From ed6e9b4ce34cabca6d251ce1633ce7d9bcecdd08 Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Sat, 6 Jul 2024 13:33:59 +0800 Subject: [PATCH 2/8] chore: compile and binary compatibility --- .../2.9.4.backwards.excludes/issue-32465.excludes | 5 +++++ .../main/scala/akka/actor/typed/javadsl/Behaviors.scala | 8 +------- .../akka/cluster/typed/SingletonCompileOnlyTest.java | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes diff --git a/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes b/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes new file mode 100644 index 00000000000..95329e1ae08 --- /dev/null +++ b/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes @@ -0,0 +1,5 @@ +ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.javadsl.Behaviors.supervise") +ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.javadsl.Behaviors$Supervise") +ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors.supervise") +ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise") +ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise$") diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala index 5d77a5bf95c..9681a512ab0 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala @@ -10,13 +10,7 @@ import java.util.function.{ Supplier, Function => JFunction } import scala.reflect.ClassTag import akka.actor.typed._ -import akka.actor.typed.internal.{ - BehaviorImpl, - StashBufferImpl, - Supervisor, - TimerSchedulerImpl, - WithMdcBehaviorInterceptor -} +import akka.actor.typed.internal.{ BehaviorImpl, StashBufferImpl, TimerSchedulerImpl, WithMdcBehaviorInterceptor } import akka.japi.function.{ Effect, Function2 => JapiFunction2 } import akka.japi.pf.PFBuilder import akka.util.ccompat.JavaConverters._ diff --git a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java index 35b0165df16..738d2756d31 100644 --- a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java +++ b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java @@ -111,7 +111,7 @@ public static void backoff() { singleton.init( SingletonActor.of( Behaviors.supervise(Counter.create()) - .onFailure( + .onAnyFailure( SupervisorStrategy.restartWithBackoff( Duration.ofSeconds(1), Duration.ofSeconds(10), 0.2)), "GlobalCounter")); From 71e27a26c4255715796d3d2c93be7e6aa1851f75 Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Mon, 8 Jul 2024 08:52:50 +0800 Subject: [PATCH 3/8] chore: scala3 binary compatibility --- .../mima-filters/2.9.4.backwards.excludes/issue-32465.excludes | 1 + 1 file changed, 1 insertion(+) diff --git a/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes b/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes index 95329e1ae08..9254a81f294 100644 --- a/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes +++ b/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes @@ -3,3 +3,4 @@ ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.javadsl.Behaviors$ ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors.supervise") ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise") ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise$") +ProblemFilters.exclude[MissingFieldProblem]("akka.actor.typed.scaladsl.Behaviors.Supervise") From 82ee194678944377086ef217dc5b3cfc67ff7cbf Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Mon, 8 Jul 2024 16:14:27 +0800 Subject: [PATCH 4/8] chore: remove mima filters --- .../2.9.4.backwards.excludes/issue-32465.excludes | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes diff --git a/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes b/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes deleted file mode 100644 index 9254a81f294..00000000000 --- a/akka-actor-typed/src/main/mima-filters/2.9.4.backwards.excludes/issue-32465.excludes +++ /dev/null @@ -1,6 +0,0 @@ -ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.javadsl.Behaviors.supervise") -ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.javadsl.Behaviors$Supervise") -ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors.supervise") -ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise") -ProblemFilters.exclude[MissingClassProblem]("akka.actor.typed.scaladsl.Behaviors$Supervise$") -ProblemFilters.exclude[MissingFieldProblem]("akka.actor.typed.scaladsl.Behaviors.Supervise") From ac9b572ec30e100dca090e647c4c08c735f7a133 Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Mon, 8 Jul 2024 17:27:01 +0800 Subject: [PATCH 5/8] fix binary compatibility --- .../test/java/jdocs/akka/typed/RouterTest.java | 2 +- .../supervision/SupervisionCompileOnlyTest.java | 10 +++++----- .../main/scala/akka/actor/typed/Behavior.scala | 2 +- .../akka/actor/typed/javadsl/Behaviors.scala | 15 +++++++++++++-- .../akka/actor/typed/scaladsl/Behaviors.scala | 6 ++++-- .../cluster/typed/SingletonCompileOnlyTest.java | 2 +- .../tutorial_1/ActorHierarchyExperiments.java | 2 +- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java index ccce159867d..360751660bd 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java @@ -124,7 +124,7 @@ static Behavior showPoolRouting() { Routers.pool( poolSize, // make sure the workers are restarted if they fail - Behaviors.supervise(Worker.create()).onAnyFailure(SupervisorStrategy.restart())); + Behaviors.supervise(Worker.create()).onFailure(SupervisorStrategy.restart())); ActorRef router = context.spawn(pool, "worker-pool"); for (int i = 0; i < 10; i++) { diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java index 64876805fac..1a1baadb0af 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java @@ -33,7 +33,7 @@ public Got(int n) { // #top-level public static Behavior create() { - return Behaviors.supervise(counter(1)).onAnyFailure(SupervisorStrategy.restart()); + return Behaviors.supervise(counter(1)).onFailure(SupervisorStrategy.restart()); } // #top-level @@ -105,7 +105,7 @@ static Behavior parent() { return Behaviors.same(); }); })) - .onAnyFailure(SupervisorStrategy.restart()); + .onFailure(SupervisorStrategy.restart()); } // #restart-stop-children @@ -117,8 +117,8 @@ static Behavior parent2() { final ActorRef child2 = ctx.spawn(child(0), "child2"); // supervision strategy inside the setup to not recreate children on restart - return Behaviors.supervise( - Behaviors.receiveMessage( + return Behaviors.supervise( + Behaviors.receiveMessage( msg -> { // message handling that might throw an exception String[] parts = msg.split(" "); @@ -126,7 +126,7 @@ static Behavior parent2() { child2.tell(parts[1]); return Behaviors.same(); })) - .onAnyFailure(SupervisorStrategy.restart().withStopChildren(false)); + .onFailure(SupervisorStrategy.restart().withStopChildren(false)); }); } // #restart-keep-children diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala index 7aa958edce3..d4d8bfd4a5a 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala @@ -118,7 +118,7 @@ abstract class ExtensibleBehavior[T] extends Behavior[T](BehaviorTags.Extensible * A behavior type that could be supervised, Not for user extension. */ @InternalApi -final class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) +class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) extends Behavior[T](BehaviorTags.SuperviseBehavior) { private final val ThrowableClassTag = ClassTag(classOf[Throwable]) diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala index 9681a512ab0..255a25cffe0 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala @@ -244,8 +244,19 @@ object Behaviors { * .onFailure[IndexOutOfBoundsException](SupervisorStrategy.resume) // resume for IndexOutOfBoundsException exceptions * }}} */ - def supervise[T](wrapped: Behavior[T]): SuperviseBehavior[T] = - scaladsl.Behaviors.supervise(wrapped) + def supervise[T](wrapped: Behavior[T]): Supervise[T] = + new Supervise[T](wrapped) + + final class Supervise[T] private[akka] (wrapped: Behavior[T]) extends SuperviseBehavior(wrapped) { + + /** + * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. + * + * All non-fatal (see [[scala.util.control.NonFatal]]) exceptions types will be handled using the given strategy. + */ + def onFailure(strategy: SupervisorStrategy): Behavior[T] = + onFailure(classOf[Exception], strategy) + } /** * Transform the incoming messages by placing a funnel in front of the wrapped `Behavior`: the supplied diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala index 9092cef195f..4a48ef8f5d6 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala @@ -215,8 +215,10 @@ object Behaviors { * .onFailure[IndexOutOfBoundsException](SupervisorStrategy.resume) // resume for IndexOutOfBoundsException exceptions * }}} */ - def supervise[T](wrapped: Behavior[T]): SuperviseBehavior[T] = - new SuperviseBehavior[T](wrapped) + def supervise[T](wrapped: Behavior[T]): Supervise[T] = + new Supervise[T](wrapped) + + final class Supervise[T] private[akka] (wrapped: Behavior[T]) extends SuperviseBehavior(wrapped) /** * Support for scheduled `self` messages in an actor. diff --git a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java index 738d2756d31..35b0165df16 100644 --- a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java +++ b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java @@ -111,7 +111,7 @@ public static void backoff() { singleton.init( SingletonActor.of( Behaviors.supervise(Counter.create()) - .onAnyFailure( + .onFailure( SupervisorStrategy.restartWithBackoff( Duration.ofSeconds(1), Duration.ofSeconds(10), 0.2)), "GlobalCounter")); diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java index 5292b3f5419..3681f6c094d 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java @@ -111,7 +111,7 @@ private SupervisingActor(ActorContext context) { super(context); child = context.spawn( - Behaviors.supervise(SupervisedActor.create()).onAnyFailure(SupervisorStrategy.restart()), + Behaviors.supervise(SupervisedActor.create()).onFailure(SupervisorStrategy.restart()), "supervised-actor"); } From 2199266fd0fcb4747a93941a96539d40b9e29dba Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Sat, 24 Aug 2024 12:34:22 +0800 Subject: [PATCH 6/8] binary compatibility --- .../2.9.6.backwards.excludes/issue-32465.excludes | 4 ++++ .../main/scala/akka/actor/typed/Behavior.scala | 15 ++------------- .../akka/actor/typed/javadsl/Behaviors.scala | 12 ++++++++++-- .../akka/actor/typed/scaladsl/Behaviors.scala | 9 +++++++-- 4 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes diff --git a/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes b/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes new file mode 100644 index 00000000000..ed70ef63e1e --- /dev/null +++ b/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes @@ -0,0 +1,4 @@ +# Change the return type of `Behaviors.supervise` to support flattened supervision +ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.javadsl.Behaviors#Supervise.onFailure") +ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors#Supervise.onFailure") +ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors#Supervise.onFailure$extension") diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala index d4d8bfd4a5a..1a135a1d07c 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala @@ -7,6 +7,7 @@ package akka.actor.typed import scala.annotation.switch import scala.annotation.tailrec import scala.reflect.ClassTag + import akka.actor.InvalidMessageException import akka.actor.typed.internal.BehaviorImpl import akka.actor.typed.internal.BehaviorImpl.DeferredBehavior @@ -130,24 +131,12 @@ class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) } /** - * Java API: * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. * * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. */ - def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = { + def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = onFailure(strategy)(ClassTag(clazz)) - } - - /** - * Java API: - * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. - * - * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. - */ - def onAnyFailure[Thr <: Throwable](strategy: SupervisorStrategy): SuperviseBehavior[T] = { - onFailure(classOf[Exception], strategy) - } private[akka] def unwrap: Behavior[T] = wrapped } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala index 255a25cffe0..38a64ae2036 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala @@ -247,7 +247,15 @@ object Behaviors { def supervise[T](wrapped: Behavior[T]): Supervise[T] = new Supervise[T](wrapped) - final class Supervise[T] private[akka] (wrapped: Behavior[T]) extends SuperviseBehavior(wrapped) { + final class Supervise[T] private[akka] (wrapped: Behavior[T]) { + + /** + * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. + * + * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. + */ + def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = + new SuperviseBehavior[T](wrapped).onFailure(clazz, strategy) /** * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. @@ -255,7 +263,7 @@ object Behaviors { * All non-fatal (see [[scala.util.control.NonFatal]]) exceptions types will be handled using the given strategy. */ def onFailure(strategy: SupervisorStrategy): Behavior[T] = - onFailure(classOf[Exception], strategy) + new SuperviseBehavior[T](wrapped).onFailure(strategy) } /** diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala index 4a48ef8f5d6..457c4ab6980 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala @@ -6,7 +6,6 @@ package akka.actor.typed package scaladsl import scala.reflect.ClassTag - import akka.actor.typed.internal._ import akka.annotation.{ DoNotInherit, InternalApi } @@ -218,7 +217,13 @@ object Behaviors { def supervise[T](wrapped: Behavior[T]): Supervise[T] = new Supervise[T](wrapped) - final class Supervise[T] private[akka] (wrapped: Behavior[T]) extends SuperviseBehavior(wrapped) + final class Supervise[T] private[akka] (val wrapped: Behavior[T]) extends AnyVal { + + /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ + def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)(implicit tag: ClassTag[Thr]): SuperviseBehavior[T] = { + new SuperviseBehavior[T](wrapped).onFailure(strategy)(tag) + } + } /** * Support for scheduled `self` messages in an actor. From 92021e9f02d5809bd9deb1ec1b6fefa5d2532195 Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Thu, 29 Aug 2024 21:14:36 +0800 Subject: [PATCH 7/8] avoid method signature change --- .../actor/typed/javadsl/ActorCompile.java | 10 ++- .../SupervisionCompileOnlyTest.java | 4 +- .../akka/actor/typed/SupervisionSpec.scala | 75 ++++++++++++++----- .../supervision/SupervisionCompileOnly.scala | 9 ++- .../issue-32465.excludes | 4 - .../scala/akka/actor/typed/Behavior.scala | 6 +- .../akka/actor/typed/javadsl/Behaviors.scala | 14 +++- .../akka/actor/typed/scaladsl/Behaviors.scala | 10 ++- 8 files changed, 96 insertions(+), 36 deletions(-) delete mode 100644 akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes diff --git a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java index e48cefb0f4a..a407c49dda5 100644 --- a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java +++ b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ActorCompile.java @@ -173,9 +173,15 @@ public Behavior receive(TypedActorContext context, MyMsg message) SupervisorStrategy strategy7 = strategy6.withResetBackoffAfter(Duration.ofSeconds(2)); Behavior behv = - Behaviors.supervise(Behaviors.ignore()) - .onFailure(IllegalStateException.class, strategy6) + Behaviors.supervise( + Behaviors.supervise(Behaviors.ignore()) + .onFailure(IllegalStateException.class, strategy6)) .onFailure(RuntimeException.class, strategy1); + // or using flattern API: + Behavior flatternBehv = + Behaviors.supervise(Behaviors.ignore()) + .whenFailure(IllegalStateException.class, strategy6) + .whenFailure(RuntimeException.class, strategy1); } // actor context diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java index 1a1baadb0af..2df4265eb09 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/supervision/SupervisionCompileOnlyTest.java @@ -117,8 +117,8 @@ static Behavior parent2() { final ActorRef child2 = ctx.spawn(child(0), "child2"); // supervision strategy inside the setup to not recreate children on restart - return Behaviors.supervise( - Behaviors.receiveMessage( + return Behaviors.supervise( + Behaviors.receiveMessage( msg -> { // message handling that might throw an exception String[] parts = msg.split(" "); diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala index 61c388a5401..e1d670cbb49 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala @@ -164,11 +164,9 @@ class StubbedSupervisionSpec extends AnyWordSpec with Matchers with LogCapturing inbox.receiveMessage() should ===(State(1, Map.empty)) } - "support nesting to handle different exceptions" in { + def testNestedSupervision[T](supervisedBehavior: Behavior[Command] => Behavior[Command]): Unit = { val inbox = TestInbox[Event]("evt") - val behv = supervise(targetBehavior(inbox.ref)) - .onFailure[Exc2](SupervisorStrategy.resume) - .onFailure[Exc3](SupervisorStrategy.restart) + val behv = supervisedBehavior(targetBehavior(inbox.ref)) val testkit = BehaviorTestKit(behv) testkit.run(IncrementState) testkit.run(GetState) @@ -192,6 +190,14 @@ class StubbedSupervisionSpec extends AnyWordSpec with Matchers with LogCapturing inbox.receiveMessage() should ===(ReceivedSignal(PostStop)) } + "support nesting to handle different exceptions" in testNestedSupervision { behv => + supervise(supervise(behv).onFailure[Exc2](SupervisorStrategy.resume)).onFailure[Exc3](SupervisorStrategy.restart) + } + + "flatten support nesting to handle different exceptions" in testNestedSupervision { behv => + supervise(behv).whenFailure[Exc2](SupervisorStrategy.resume).whenFailure[Exc3](SupervisorStrategy.restart) + } + "not catch fatal error" in { val inbox = TestInbox[Event]() val behv = Behaviors.supervise(targetBehavior(inbox.ref)).onFailure[Throwable](SupervisorStrategy.restart) @@ -397,11 +403,9 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" } } - "support nesting exceptions with different strategies" in { + def testNestedSupervision[T](supervisedBehavior: Behavior[Command] => Behavior[Command]): Unit = { val probe = TestProbe[Event]("evt") - val behv = - supervise(supervise(targetBehavior(probe.ref)).onFailure[RuntimeException](SupervisorStrategy.stop)) - .onFailure[Exception](SupervisorStrategy.restart) + val behv = supervisedBehavior(targetBehavior(probe.ref)) val ref = spawn(behv) @@ -416,13 +420,21 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" } } - "support nesting exceptions with outer restart and inner backoff strategies" in { + "support nesting exceptions with different strategies" in testNestedSupervision { behv => + supervise(supervise(behv).onFailure[RuntimeException](SupervisorStrategy.stop)) + .onFailure[Exception](SupervisorStrategy.restart) + } + + "flatten support nesting exceptions with different strategies" in testNestedSupervision { behv => + supervise(behv) + .whenFailure[RuntimeException](SupervisorStrategy.stop) + .whenFailure[Exception](SupervisorStrategy.restart) + } + + def testNestedSupervisionWithRestartThenBackoff[T]( + supervisedBehavior: Behavior[Command] => Behavior[Command]): Unit = { val probe = TestProbe[Event]("evt") - val behv = - supervise( - supervise(targetBehavior(probe.ref)) - .onFailure[IllegalArgumentException](SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0))) - .onFailure[IOException](SupervisorStrategy.restart) + val behv = supervisedBehavior(targetBehavior(probe.ref)) val ref = spawn(behv) @@ -444,11 +456,25 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" probe.expectMessage(Pong(2)) } - "support nesting exceptions with inner restart and outer backoff strategies" in { + "support nesting exceptions with outer restart and inner backoff strategies" in testNestedSupervisionWithRestartThenBackoff { + behv => + supervise( + supervise(behv).onFailure[IllegalArgumentException]( + SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0))) + .onFailure[IOException](SupervisorStrategy.restart) + } + + "flatten support nesting exceptions with outer restart and inner backoff strategies" in testNestedSupervisionWithRestartThenBackoff { + behv => + supervise(behv) + .whenFailure[IllegalArgumentException](SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0)) + .whenFailure[IOException](SupervisorStrategy.restart) + } + + def testNestedSupervisionWithBackoffThenRestart[T]( + supervisedBehavior: Behavior[Command] => Behavior[Command]): Unit = { val probe = TestProbe[Event]("evt") - val behv = - supervise(supervise(targetBehavior(probe.ref)).onFailure[IllegalArgumentException](SupervisorStrategy.restart)) - .onFailure[IOException](SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0)) + val behv = supervisedBehavior(targetBehavior(probe.ref)) val ref = spawn(behv) @@ -470,6 +496,19 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" probe.expectMessage(Pong(2)) } + "support nesting exceptions with inner restart and outer backoff strategies" in testNestedSupervisionWithBackoffThenRestart { + behv => + supervise(supervise(behv).onFailure[IllegalArgumentException](SupervisorStrategy.restart)) + .onFailure[IOException](SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0)) + } + + "flatten support nesting exceptions with inner restart and outer backoff strategies" in testNestedSupervisionWithBackoffThenRestart { + behv => + supervise(behv) + .whenFailure[IllegalArgumentException](SupervisorStrategy.restart) + .whenFailure[IOException](SupervisorStrategy.restartWithBackoff(10.millis, 10.millis, 0.0)) + } + "stop when not supervised" in { val probe = TestProbe[Event]("evt") val behv = targetBehavior(probe.ref) diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala index 563e34b2859..6de3b79e69e 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/supervision/SupervisionCompileOnly.scala @@ -34,9 +34,14 @@ object SupervisionCompileOnly { //#multiple Behaviors - .supervise(behavior) - .onFailure[IllegalStateException](SupervisorStrategy.restart) + .supervise(Behaviors.supervise(behavior).onFailure[IllegalStateException](SupervisorStrategy.restart)) .onFailure[IllegalArgumentException](SupervisorStrategy.stop) + + // or flatten ways + Behaviors + .supervise(behavior) + .whenFailure[IllegalStateException](SupervisorStrategy.restart) + .whenFailure[IllegalArgumentException](SupervisorStrategy.stop) //#multiple //#wrap diff --git a/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes b/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes deleted file mode 100644 index ed70ef63e1e..00000000000 --- a/akka-actor-typed/src/main/mima-filters/2.9.6.backwards.excludes/issue-32465.excludes +++ /dev/null @@ -1,4 +0,0 @@ -# Change the return type of `Behaviors.supervise` to support flattened supervision -ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.javadsl.Behaviors#Supervise.onFailure") -ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors#Supervise.onFailure") -ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.actor.typed.scaladsl.Behaviors#Supervise.onFailure$extension") diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala index 1a135a1d07c..0babf6c11a1 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala @@ -124,7 +124,7 @@ class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) private final val ThrowableClassTag = ClassTag(classOf[Throwable]) /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ - def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)( + def whenFailure[Thr <: Throwable](strategy: SupervisorStrategy)( implicit tag: ClassTag[Thr] = ThrowableClassTag): SuperviseBehavior[T] = { val effectiveTag = if (tag == ClassTag.Nothing) ThrowableClassTag else tag new SuperviseBehavior[T](Supervisor(Behavior.validateAsInitial(wrapped), strategy)(effectiveTag)) @@ -135,8 +135,8 @@ class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) * * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. */ - def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = - onFailure(strategy)(ClassTag(clazz)) + def whenFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = + whenFailure(strategy)(ClassTag(clazz)) private[akka] def unwrap: Behavior[T] = wrapped } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala index 38a64ae2036..a74bbaadce5 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/Behaviors.scala @@ -254,8 +254,8 @@ object Behaviors { * * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. */ - def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = - new SuperviseBehavior[T](wrapped).onFailure(clazz, strategy) + def onFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): Behavior[T] = + new SuperviseBehavior[T](wrapped).whenFailure(clazz, strategy).unwrap /** * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. @@ -263,7 +263,15 @@ object Behaviors { * All non-fatal (see [[scala.util.control.NonFatal]]) exceptions types will be handled using the given strategy. */ def onFailure(strategy: SupervisorStrategy): Behavior[T] = - new SuperviseBehavior[T](wrapped).onFailure(strategy) + onFailure(classOf[Exception], strategy) + + /** + * Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws by use flatten ways. + * + * Only exceptions of the given type (and their subclasses) will be handled by this supervision behavior. + */ + def whenFailure[Thr <: Throwable](clazz: Class[Thr], strategy: SupervisorStrategy): SuperviseBehavior[T] = + new SuperviseBehavior[T](wrapped).whenFailure(clazz, strategy) } /** diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala index 457c4ab6980..217fffc937b 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala @@ -220,8 +220,14 @@ object Behaviors { final class Supervise[T] private[akka] (val wrapped: Behavior[T]) extends AnyVal { /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ - def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)(implicit tag: ClassTag[Thr]): SuperviseBehavior[T] = { - new SuperviseBehavior[T](wrapped).onFailure(strategy)(tag) + def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)(implicit tag: ClassTag[Thr]): Behavior[T] = { + whenFailure(strategy)(tag).unwrap + } + + /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws by use flatten ways. */ + def whenFailure[Thr <: Throwable](strategy: SupervisorStrategy)( + implicit tag: ClassTag[Thr]): SuperviseBehavior[T] = { + new SuperviseBehavior[T](wrapped).whenFailure(strategy)(tag) } } From 31a19dfe7526312cdeff462bc2e7f3547ec3ea95 Mon Sep 17 00:00:00 2001 From: JingZhang Chen Date: Fri, 30 Aug 2024 01:37:01 +0800 Subject: [PATCH 8/8] trying to avoid binary issue --- .../src/main/scala/akka/actor/typed/Behavior.scala | 3 +-- .../scala/akka/actor/typed/scaladsl/Behaviors.scala | 10 +++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala index 0babf6c11a1..cf06569ef65 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Behavior.scala @@ -124,8 +124,7 @@ class SuperviseBehavior[T] private[akka] (val wrapped: Behavior[T]) private final val ThrowableClassTag = ClassTag(classOf[Throwable]) /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ - def whenFailure[Thr <: Throwable](strategy: SupervisorStrategy)( - implicit tag: ClassTag[Thr] = ThrowableClassTag): SuperviseBehavior[T] = { + def whenFailure[Thr <: Throwable](strategy: SupervisorStrategy)(implicit tag: ClassTag[Thr]): SuperviseBehavior[T] = { val effectiveTag = if (tag == ClassTag.Nothing) ThrowableClassTag else tag new SuperviseBehavior[T](Supervisor(Behavior.validateAsInitial(wrapped), strategy)(effectiveTag)) } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala index 217fffc937b..e51541d9fe8 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/Behaviors.scala @@ -6,6 +6,7 @@ package akka.actor.typed package scaladsl import scala.reflect.ClassTag + import akka.actor.typed.internal._ import akka.annotation.{ DoNotInherit, InternalApi } @@ -217,16 +218,19 @@ object Behaviors { def supervise[T](wrapped: Behavior[T]): Supervise[T] = new Supervise[T](wrapped) + private final val ThrowableClassTag = ClassTag(classOf[Throwable]) final class Supervise[T] private[akka] (val wrapped: Behavior[T]) extends AnyVal { /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws. */ - def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)(implicit tag: ClassTag[Thr]): Behavior[T] = { - whenFailure(strategy)(tag).unwrap + def onFailure[Thr <: Throwable](strategy: SupervisorStrategy)( + implicit tag: ClassTag[Thr] = ThrowableClassTag): Behavior[T] = { + val effectiveTag = if (tag == ClassTag.Nothing) ThrowableClassTag else tag + Supervisor(Behavior.validateAsInitial(wrapped), strategy)(effectiveTag) } /** Specify the [[SupervisorStrategy]] to be invoked when the wrapped behavior throws by use flatten ways. */ def whenFailure[Thr <: Throwable](strategy: SupervisorStrategy)( - implicit tag: ClassTag[Thr]): SuperviseBehavior[T] = { + implicit tag: ClassTag[Thr] = ThrowableClassTag): SuperviseBehavior[T] = { new SuperviseBehavior[T](wrapped).whenFailure(strategy)(tag) } }