Skip to content

Commit

Permalink
Make Behaviors.intercept a factory () => BehaviorInterceptor, akka#26728
Browse files Browse the repository at this point in the history
  • Loading branch information
chbatey authored and patriknw committed Jun 14, 2019
1 parent edbe7d0 commit 31def70
Show file tree
Hide file tree
Showing 19 changed files with 87 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,20 @@ public MyMsgB(String greeting) {
Behavior<MyMsg> actor5 = ignore();
Behavior<MyMsg> actor6 =
intercept(
new BehaviorInterceptor<MyMsg, MyMsg>() {
@Override
public Behavior<MyMsg> aroundReceive(
TypedActorContext<MyMsg> context, MyMsg message, ReceiveTarget<MyMsg> target) {
return target.apply(context, message);
}

@Override
public Behavior<MyMsg> aroundSignal(
TypedActorContext<MyMsg> context, Signal signal, SignalTarget<MyMsg> target) {
return target.apply(context, signal);
}
},
() ->
new BehaviorInterceptor<MyMsg, MyMsg>() {
@Override
public Behavior<MyMsg> aroundReceive(
TypedActorContext<MyMsg> context, MyMsg message, ReceiveTarget<MyMsg> target) {
return target.apply(context, message);
}

@Override
public Behavior<MyMsg> aroundSignal(
TypedActorContext<MyMsg> context, Signal signal, SignalTarget<MyMsg> target) {
return target.apply(context, signal);
}
},
actor5);
Behavior<MyMsgA> actor7 = actor6.narrow();
Behavior<MyMsg> actor8 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public Behavior<String> aroundSignal(
ActorRef<String> ref =
testKit.spawn(
Behaviors.intercept(
interceptor,
() -> interceptor,
Behaviors.receiveMessage(
(String msg) -> {
probe.getRef().tell(msg);
Expand Down Expand Up @@ -87,7 +87,7 @@ public Behavior<Message> aroundSignal(
ActorRef<Message> ref =
testKit.spawn(
Behaviors.intercept(
interceptor,
() -> interceptor,
Behaviors.receiveMessage(
(Message msg) -> {
probe.getRef().tell(msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -708,5 +708,5 @@ class InterceptActorContextSpec extends ActorContextSpec {
target(context, signal)
}

override def decoration[T]: Behavior[T] => Behavior[T] = b => Behaviors.intercept[T, T](tap)(b)
override def decoration[T]: Behavior[T] => Behavior[T] = b => Behaviors.intercept[T, T](() => tap)(b)
}
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ class InterceptScalaBehaviorSpec extends ImmutableWithSignalScalaBehaviorSpec wi
target(context, signal)
}
}
(SBehaviors.intercept(tap)(super.behavior(monitor)._1), inbox)
(SBehaviors.intercept(() => tap)(super.behavior(monitor)._1), inbox)
}
}

Expand Down Expand Up @@ -633,7 +633,7 @@ class TapJavaBehaviorSpec extends ImmutableWithSignalJavaBehaviorSpec with Reuse
target(context, signal)
}
}
(JBehaviors.intercept(tap, super.behavior(monitor)._1), inbox)
(JBehaviors.intercept(() => tap, super.behavior(monitor)._1), inbox)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
val probe = TestProbe[String]()
val interceptor = snitchingInterceptor(probe.ref)

val ref: ActorRef[String] = spawn(Behaviors.intercept(interceptor)(Behaviors.receiveMessage[String] { m =>
val ref: ActorRef[String] = spawn(Behaviors.intercept(() => interceptor)(Behaviors.receiveMessage[String] { m =>
probe.ref ! s"actual behavior $m"
Behaviors.same
}))
Expand All @@ -95,10 +95,10 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""

val interceptor = snitchingInterceptor(probe.ref)
def intercept(beh: Behavior[String]): Behavior[String] =
Behaviors.intercept(interceptor)(beh)
Behaviors.intercept(() => interceptor)(beh)

val beh: Behavior[String] =
intercept(intercept(Behaviors.receiveMessage(m => Behaviors.same)))
intercept(intercept(Behaviors.receiveMessage(_ => Behaviors.same)))

val ref = spawn(beh)

Expand All @@ -113,7 +113,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""

val interceptor = snitchingInterceptor(probe.ref)
def next(count: Int): Behavior[String] =
Behaviors.intercept(interceptor)(Behaviors.receiveMessage(m => next(count + 1)))
Behaviors.intercept(() => interceptor)(Behaviors.receiveMessage(_ => next(count + 1)))

val ref = spawn(next(1))

Expand All @@ -137,10 +137,10 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""

def intercept(beh: Behavior[String]): Behavior[String] =
// a new interceptor instance every call
Behaviors.intercept(snitchingInterceptor(probe.ref))(beh)
Behaviors.intercept(() => snitchingInterceptor(probe.ref))(beh)

val beh: Behavior[String] =
intercept(intercept(Behaviors.receiveMessage(m => Behaviors.same)))
intercept(intercept(Behaviors.receiveMessage(_ => Behaviors.same)))

val ref = spawn(beh)

Expand All @@ -158,7 +158,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
def next(count: Int): Behavior[String] =
Behaviors.intercept(
// a new instance every "recursion"
snitchingInterceptor(probe.ref))(Behaviors.receiveMessage(m => next(count + 1)))
() => snitchingInterceptor(probe.ref))(Behaviors.receiveMessage(_ => next(count + 1)))

val ref = spawn(next(1))

Expand Down Expand Up @@ -196,7 +196,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
}

val innerBehaviorStarted = new AtomicBoolean(false)
val ref = spawn(Behaviors.intercept(interceptor)(Behaviors.setup { context =>
val ref = spawn(Behaviors.intercept(() => interceptor)(Behaviors.setup { _ =>
innerBehaviorStarted.set(true)
Behaviors.unhandled[String]
}))
Expand All @@ -210,7 +210,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
val probe = TestProbe[String]()
val interceptor = snitchingInterceptor(probe.ref)

val ref: ActorRef[String] = spawn(Behaviors.intercept(interceptor)(Behaviors.setup { _ =>
val ref: ActorRef[String] = spawn(Behaviors.intercept(() => interceptor)(Behaviors.setup { _ =>
var count = 0
Behaviors.receiveMessage[String] { m =>
count += 1
Expand All @@ -235,7 +235,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
val interceptor = snitchingInterceptor(probe.ref)

def next(count1: Int): Behavior[String] = {
Behaviors.intercept(interceptor)(Behaviors.setup { _ =>
Behaviors.intercept(() => interceptor)(Behaviors.setup { _ =>
var count2 = 0
Behaviors.receiveMessage[String] { m =>
count2 += 1
Expand Down Expand Up @@ -268,7 +268,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
val interceptor = snitchingInterceptor(probe.ref)

EventFilter[ActorInitializationException](occurrences = 1).intercept {
val ref = spawn(Behaviors.intercept(interceptor)(Behaviors.setup[String] { _ =>
val ref = spawn(Behaviors.intercept(() => interceptor)(Behaviors.setup[String] { _ =>
Behaviors.same[String]
}))
probe.expectTerminated(ref, probe.remainingOrDefault)
Expand Down Expand Up @@ -304,7 +304,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
}

val decorated: Behavior[Msg] =
Behaviors.intercept(poisonInterceptor)(inner(0)).narrow
Behaviors.intercept(() => poisonInterceptor)(inner(0)).narrow

val ref = spawn(decorated)
val probe = TestProbe[String]()
Expand Down Expand Up @@ -345,7 +345,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
}

val probe = TestProbe[Message]()
val ref = spawn(Behaviors.intercept(partialInterceptor)(Behaviors.receiveMessage { msg =>
val ref = spawn(Behaviors.intercept(() => partialInterceptor)(Behaviors.receiveMessage { msg =>
probe.ref ! msg
Behaviors.same
}))
Expand Down Expand Up @@ -379,7 +379,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""
}
}

val ref = spawn(Behaviors.intercept(postStopInterceptor)(Behaviors.receiveMessage[String] { _ =>
val ref = spawn(Behaviors.intercept(() => postStopInterceptor)(Behaviors.receiveMessage[String] { _ =>
Behaviors.stopped { () =>
probe.ref ! "callback-post-stop"
}
Expand All @@ -394,7 +394,7 @@ class InterceptSpec extends ScalaTestWithActorTestKit("""

"not grow stack when nesting same interceptor" in {
def next(n: Int, p: ActorRef[Array[StackTraceElement]]): Behavior[String] = {
Behaviors.intercept(new SameTypeInterceptor) {
Behaviors.intercept(() => new SameTypeInterceptor) {

Behaviors.receiveMessage { _ =>
if (n == 20) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1095,15 +1095,16 @@ class SupervisionSpec extends ScalaTestWithActorTestKit("""
case "boom" => throw TestException("boom indeed")
case "switch" =>
supervise[String](setup(_ =>
supervise[String](Behaviors.intercept(whateverInterceptor)(supervise[String](Behaviors.receiveMessage {
case "boom" => throw TestException("boom indeed")
case "ping" =>
probe.ref ! "pong"
Behaviors.same
case "give me stacktrace" =>
probe.ref ! new RuntimeException().getStackTrace.toVector
Behaviors.stopped
}).onFailure[RuntimeException](SupervisorStrategy.resume)))
supervise[String](
Behaviors.intercept(() => whateverInterceptor)(supervise[String](Behaviors.receiveMessage {
case "boom" => throw TestException("boom indeed")
case "ping" =>
probe.ref ! "pong"
Behaviors.same
case "give me stacktrace" =>
probe.ref ! new RuntimeException().getStackTrace.toVector
Behaviors.stopped
}).onFailure[RuntimeException](SupervisorStrategy.resume)))
.onFailure[IllegalArgumentException](SupervisorStrategy.restart.withLimit(23, 10.seconds))))
.onFailure[RuntimeException](SupervisorStrategy.restart)
}).onFailure[RuntimeException](SupervisorStrategy.stop)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,22 @@ class StopSpec extends ScalaTestWithActorTestKit with WordSpecLike {
"execute the post stop when wrapped" in {
val probe = TestProbe[Done]()
spawn(Behaviors.setup[AnyRef] { _ =>
Behaviors.intercept(new BehaviorInterceptor[AnyRef, AnyRef] {
override def aroundReceive(
context: typed.TypedActorContext[AnyRef],
message: AnyRef,
target: ReceiveTarget[AnyRef]): Behavior[AnyRef] = {
target(context, message)
}
Behaviors.intercept(() =>
new BehaviorInterceptor[AnyRef, AnyRef] {
override def aroundReceive(
context: typed.TypedActorContext[AnyRef],
message: AnyRef,
target: ReceiveTarget[AnyRef]): Behavior[AnyRef] = {
target(context, message)
}

override def aroundSignal(
context: typed.TypedActorContext[AnyRef],
signal: Signal,
target: SignalTarget[AnyRef]): Behavior[AnyRef] = {
target(context, signal)
}
})(Behaviors.stopped { () =>
override def aroundSignal(
context: typed.TypedActorContext[AnyRef],
signal: Signal,
target: SignalTarget[AnyRef]): Behavior[AnyRef] = {
target(context, signal)
}
})(Behaviors.stopped { () =>
probe.ref ! Done
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private[akka] object BehaviorTags {
}

def widened[O, I](behavior: Behavior[I], matcher: PartialFunction[O, I]): Behavior[O] =
intercept(WidenedInterceptor(matcher))(behavior)
intercept(() => WidenedInterceptor(matcher))(behavior)

def same[T]: Behavior[T] = SameBehavior.unsafeCast[T]

Expand Down Expand Up @@ -162,7 +162,7 @@ private[akka] object BehaviorTags {
* the same interceptor (defined by the `isSame` method on the `BehaviorInterceptor`) only the innermost interceptor
* is kept. This is to protect against stack overflow when recursively defining behaviors.
*/
def intercept[O, I](interceptor: BehaviorInterceptor[O, I])(behavior: Behavior[I]): Behavior[O] =
def intercept[O, I](interceptor: () => BehaviorInterceptor[O, I])(behavior: Behavior[I]): Behavior[O] =
InterceptorImpl(interceptor, behavior)

class OrElseBehavior[T](first: Behavior[T], second: Behavior[T]) extends ExtensibleBehavior[T] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import akka.util.LineNumbers
@InternalApi
private[akka] object InterceptorImpl {

def apply[O, I](interceptor: BehaviorInterceptor[O, I], nestedBehavior: Behavior[I]): Behavior[O] = {
def apply[O, I](interceptor: () => BehaviorInterceptor[O, I], nestedBehavior: Behavior[I]): Behavior[O] = {
BehaviorImpl.DeferredBehavior[O] { ctx =>
val interceptorBehavior = new InterceptorImpl[O, I](interceptor, nestedBehavior)
val interceptorBehavior = new InterceptorImpl[O, I](interceptor(), nestedBehavior)
interceptorBehavior.preStart(ctx)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,11 @@ import akka.util.unused

strategy match {
case r: RestartOrBackoff =>
Behaviors.setup { _ =>
// deferred to make sure supervisor instance not shared among instances
Behaviors.intercept[T, T](new RestartSupervisor(initialBehavior, r))(initialBehavior)
}
Behaviors.intercept[T, T](() => new RestartSupervisor(initialBehavior, r))(initialBehavior)
case r: Resume =>
// stateless so safe to share
Behaviors.intercept[T, T](new ResumeSupervisor(r))(initialBehavior)
Behaviors.intercept[T, T](() => new ResumeSupervisor(r))(initialBehavior)
case r: Stop =>
// stateless so safe to share
Behaviors.intercept[T, T](new StopSupervisor(initialBehavior, r))(initialBehavior)
Behaviors.intercept[T, T](() => new StopSupervisor(initialBehavior, r))(initialBehavior)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import scala.collection.immutable.HashMap
mdcForMessage: T => Map[String, Any],
behavior: Behavior[T]): Behavior[T] = {

val interceptor = new WithMdcBehaviorInterceptor[T](staticMdc, mdcForMessage)
BehaviorImpl.intercept(interceptor)(behavior)
BehaviorImpl.intercept(() => new WithMdcBehaviorInterceptor[T](staticMdc, mdcForMessage))(behavior)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private[akka] final class GuardianStartupBehavior[T](val guardianBehavior: Behav
stash
.unstashAll(
ctx.asInstanceOf[ActorContext[T]],
Behaviors.intercept(new GuardianStopInterceptor[T])(guardianBehavior))
Behaviors.intercept(() => new GuardianStopInterceptor[T])(guardianBehavior))
.unsafeCast[Any])
case other =>
stash.stash(other.asInstanceOf[T])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
package akka.actor.typed.javadsl

import java.util.Collections
import java.util.function.{ Function => JFunction }
import java.util.function.{ Supplier, Function => JFunction }

import akka.actor.typed._
import akka.actor.typed.internal.{ BehaviorImpl, Supervisor, TimerSchedulerImpl, WithMdcBehaviorInterceptor }
import akka.japi.function.{ Effect, Function2 => JapiFunction2 }
import akka.japi.pf.PFBuilder
import akka.util.unused

import akka.util.ccompat.JavaConverters._

import scala.reflect.ClassTag

/**
Expand Down Expand Up @@ -170,11 +170,12 @@ object Behaviors {
* the same interceptor (defined by the [[akka.actor.typed.BehaviorInterceptor#isSame]] method) only the innermost interceptor
* is kept. This is to protect against stack overflow when recursively defining behaviors.
*
* If the interceptor does keep mutable state care must be taken to create the instance in a `setup` block
* so that a new instance is created per spawned actor rather than shared among actor instance.
* The interceptor is created with a factory function in case it has state and should not be shared.
* If the interceptor has no state the same instance can be returned from the factory to avoid unnecessary object
* creation.
*/
def intercept[O, I](behaviorInterceptor: BehaviorInterceptor[O, I], behavior: Behavior[I]): Behavior[O] =
BehaviorImpl.intercept(behaviorInterceptor)(behavior)
def intercept[O, I](behaviorInterceptor: Supplier[BehaviorInterceptor[O, I]], behavior: Behavior[I]): Behavior[O] =
BehaviorImpl.intercept(() => behaviorInterceptor.get())(behavior)

/**
* Behavior decorator that copies all received message to the designated
Expand Down
Loading

0 comments on commit 31def70

Please sign in to comment.