diff --git a/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/RouterTest.java b/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/RouterTest.java index 9ded20e546e..d0852dda26e 100644 --- a/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/RouterTest.java +++ b/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/RouterTest.java @@ -133,7 +133,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/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/supervision/SupervisionCompileOnlyTest.java b/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/supervision/SupervisionCompileOnlyTest.java index 003acc898cb..cedfeefd190 100644 --- a/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/supervision/SupervisionCompileOnlyTest.java +++ b/actor-typed-tests/src/test/java/jdocs/org/apache/pekko/typed/supervision/SupervisionCompileOnlyTest.java @@ -43,7 +43,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 @@ -114,7 +114,7 @@ static Behavior parent() { return Behaviors.same(); }); })) - .onAnyFailure(SupervisorStrategy.restart()); + .onFailure(SupervisorStrategy.restart()); } // #restart-stop-children @@ -135,7 +135,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/actor-typed/src/main/mima-filters/1.0.x.backwards.excludes/issue-3413.excludes b/actor-typed/src/main/mima-filters/1.0.x.backwards.excludes/issue-3413.excludes index 54694e993c2..8a58898b319 100644 --- a/actor-typed/src/main/mima-filters/1.0.x.backwards.excludes/issue-3413.excludes +++ b/actor-typed/src/main/mima-filters/1.0.x.backwards.excludes/issue-3413.excludes @@ -1,6 +1,21 @@ -ProblemFilters.exclude[MissingFieldProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors.Supervise") -ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors$Supervise$") -ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors$Supervise") -ProblemFilters.exclude[MissingClassProblem]("org.apache.pekko.actor.typed.javadsl.Behaviors$Supervise") -ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors.supervise") -ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.actor.typed.javadsl.Behaviors.supervise") +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Change the return type of `Behaviors.supervise` to support flattened supervision +ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.actor.typed.javadsl.Behaviors#Supervise.onFailure") +ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors#Supervise.onFailure") +ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.actor.typed.scaladsl.Behaviors#Supervise.onFailure$extension") diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/Behavior.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/Behavior.scala index 82d70be7007..b7899957009 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/Behavior.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/Behavior.scala @@ -74,7 +74,7 @@ abstract class Behavior[T](private[pekko] val _tag: Int) { behavior => * A behavior type that could be supervised, Not for user extension. */ @InternalApi -final class SuperviseBehavior[T] private[pekko] ( +class SuperviseBehavior[T] private[pekko] ( val wrapped: Behavior[T]) extends Behavior[T](BehaviorTags.SuperviseBehavior) { private final val ThrowableClassTag = ClassTag(classOf[Throwable]) @@ -86,24 +86,12 @@ final class SuperviseBehavior[T] private[pekko] ( } /** - * 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[pekko] def unwrap: Behavior[T] = wrapped } diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala index eee15baf4a5..57a57d89796 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala @@ -255,8 +255,27 @@ 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[pekko] (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. + * + * 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) + } /** * Transform the incoming messages by placing a funnel in front of the wrapped `Behavior`: the supplied diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/scaladsl/Behaviors.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/scaladsl/Behaviors.scala index 5f710008bf0..cab2654a5e4 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/scaladsl/Behaviors.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/scaladsl/Behaviors.scala @@ -15,8 +15,8 @@ package org.apache.pekko.actor.typed package scaladsl import scala.reflect.ClassTag - import org.apache.pekko +import org.apache.pekko.actor.typed.SuperviseBehavior import pekko.actor.typed.internal._ import pekko.annotation.{ DoNotInherit, InternalApi } @@ -225,8 +225,18 @@ 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) + + private final val ThrowableClassTag = ClassTag(classOf[Throwable]) + final class Supervise[T] private[pekko] (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): SuperviseBehavior[T] = { + new SuperviseBehavior[T](wrapped).onFailure(strategy)(tag) + } + } /** * Support for scheduled `self` messages in an actor. diff --git a/cluster-typed/src/test/java/jdocs/org/apache/pekko/cluster/typed/SingletonCompileOnlyTest.java b/cluster-typed/src/test/java/jdocs/org/apache/pekko/cluster/typed/SingletonCompileOnlyTest.java index 038b130e6eb..3b3f6831ddd 100644 --- a/cluster-typed/src/test/java/jdocs/org/apache/pekko/cluster/typed/SingletonCompileOnlyTest.java +++ b/cluster-typed/src/test/java/jdocs/org/apache/pekko/cluster/typed/SingletonCompileOnlyTest.java @@ -120,7 +120,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/docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java b/docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java index 11e43caed8f..60b85d1e49f 100644 --- a/docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java +++ b/docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java @@ -120,8 +120,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"); } diff --git a/persistence-typed-tests/src/test/java/org/apache/pekko/persistence/typed/javadsl/EventSourcedBehaviorJavaDslTest.java b/persistence-typed-tests/src/test/java/org/apache/pekko/persistence/typed/javadsl/EventSourcedBehaviorJavaDslTest.java index 110d2956edd..bb75d62b409 100644 --- a/persistence-typed-tests/src/test/java/org/apache/pekko/persistence/typed/javadsl/EventSourcedBehaviorJavaDslTest.java +++ b/persistence-typed-tests/src/test/java/org/apache/pekko/persistence/typed/javadsl/EventSourcedBehaviorJavaDslTest.java @@ -398,7 +398,7 @@ protected void log() { public void workWhenWrappedInOtherBehavior() { Behavior behavior = Behaviors.supervise(counter(PersistenceId.ofUniqueId("c6"))) - .onAnyFailure( + .onFailure( SupervisorStrategy.restartWithBackoff( Duration.ofSeconds(1), Duration.ofSeconds(10), 0.1)); ActorRef c = testKit.spawn(behavior);