From dba36729a0a622d1495ad1e2774b63d4bbcede86 Mon Sep 17 00:00:00 2001 From: "Andy.Chen" Date: Fri, 23 Aug 2024 15:54:59 +0800 Subject: [PATCH 1/5] feat: streamlined approach for Behaviors #1444 --- .../pekko/actor/typed/javadsl/Behaviors.scala | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 57a57d89796..c88df73cc46 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 @@ -143,6 +143,27 @@ object Behaviors { def receiveMessage[T](onMessage: pekko.japi.Function[T, Behavior[T]]): Behavior[T] = new BehaviorImpl.ReceiveBehavior((_, msg) => onMessage.apply(msg)) + /** + * Simplified version of [[receiveMessage]] with only a single argument - the message + * to be handled, but it doesn't produce a return value of next behavior. + * Useful for when the behavior doesn't want to change in runtime. + * + * Construct an actor behavior that can react to incoming messages but not to + * lifecycle signals. After spawning this actor from another actor (or as the + * guardian of an [[pekko.actor.typed.ActorSystem]]) it will be executed within an + * [[ActorContext]] that allows access to the system, spawning and watching + * other actors, etc. + * + * Compared to using [[AbstractBehavior]] this factory is a more functional style + * of defining the `Behavior`. Processing the next message will not result in + * different behavior than this one + */ + def receiveMessage[T](onMessage: pekko.japi.Procedure[T]): Behavior[T] = + new BehaviorImpl.ReceiveBehavior((_, msg) => { + onMessage.apply(msg) + same[T] + }) + /** * Construct an actor behavior that can react to both incoming messages and * lifecycle signals. After spawning this actor from another actor (or as the From 8e4e94910ea8d5558a2e71a26c1173a44ae86f67 Mon Sep 17 00:00:00 2001 From: "Andy.Chen" Date: Fri, 23 Aug 2024 16:41:23 +0800 Subject: [PATCH 2/5] rename method --- .../scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c88df73cc46..949afcd1656 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 @@ -158,7 +158,7 @@ object Behaviors { * of defining the `Behavior`. Processing the next message will not result in * different behavior than this one */ - def receiveMessage[T](onMessage: pekko.japi.Procedure[T]): Behavior[T] = + def receiveMessageWithSame[T](onMessage: pekko.japi.Procedure[T]): Behavior[T] = new BehaviorImpl.ReceiveBehavior((_, msg) => { onMessage.apply(msg) same[T] From d1079178ad8d177a76e678ef15f8d2ac28f7c4bb Mon Sep 17 00:00:00 2001 From: "Andy.Chen" Date: Sat, 24 Aug 2024 03:20:33 +0800 Subject: [PATCH 3/5] scaladsl and test --- .../pekko/actor/typed/BehaviorSpec.scala | 32 +++++++++++++++++++ .../actor/typed/scaladsl/Behaviors.scala | 19 +++++++++++ 2 files changed, 51 insertions(+) diff --git a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala index 355b50c09e8..a2b9d22b744 100644 --- a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala +++ b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala @@ -378,6 +378,38 @@ class ReceiveBehaviorSpec extends Messages with BecomeWithLifecycle with Stoppab } } +class ReceiveMessageWithSameBehaviorSpec extends Messages { + override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor, StateA) -> null + private def behv(monitor: ActorRef[Event], state: State): Behavior[Command] = { + SBehaviors.setup[Command] { context => + SBehaviors + .receiveMessageWithSame[Command] { + case GetSelf => + monitor ! Self(context.self) + case Miss => + monitor ! Missed + case Ignore => + monitor ! Ignored + case Ping => + monitor ! Pong + behv(monitor, state) + case Swap => + monitor ! Swapped + behv(monitor, state.next) + case GetState() => + monitor ! state + case Stop => SBehaviors.stopped + case _: AuxPing => SBehaviors.unhandled + } + .receiveSignal { + case (_, signal) => + monitor ! ReceivedSignal(signal) + SBehaviors.same + } + } + } +} + class ImmutableWithSignalScalaBehaviorSpec extends Messages with BecomeWithLifecycle with Stoppable { override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor) -> null 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 cab2654a5e4..cbac507ccce 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 @@ -133,6 +133,25 @@ object Behaviors { def receiveMessage[T](onMessage: T => Behavior[T]): Receive[T] = new ReceiveMessageImpl(onMessage) + /** + * Simplified version of [[receiveMessage]] with only a single argument - the message + * to be handled, but it doesn't produce a return value of next behavior. + * Useful for when the behavior doesn't want to change in runtime. + * + * Construct an actor behavior that can react to incoming messages but not to + * lifecycle signals. After spawning this actor from another actor (or as the + * guardian of an [[pekko.actor.typed.ActorSystem]]) it will be executed within an + * [[ActorContext]] that allows access to the system, spawning and watching + * other actors, etc. + * + * Compared to using [[AbstractBehavior]] this factory is a more functional style + * of defining the `Behavior`. Processing the next message will not result in + * different behavior than this one + */ + def receiveMessageWithSame[T](onMessage: T => Unit): Receive[T] = { + new ReceiveMessageImpl(onMessage.andThen(_ => same)) + } + /** * Construct an actor `Behavior` from a partial message handler which treats undefined messages as unhandled. */ From 0c76ad9d4dfdcdbcc392b6285df733e9de219753 Mon Sep 17 00:00:00 2001 From: "Andy.Chen" Date: Sat, 24 Aug 2024 03:25:58 +0800 Subject: [PATCH 4/5] simpler test --- .../pekko/actor/typed/BehaviorSpec.scala | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala index a2b9d22b744..47acbd0cd0b 100644 --- a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala +++ b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/BehaviorSpec.scala @@ -379,34 +379,18 @@ class ReceiveBehaviorSpec extends Messages with BecomeWithLifecycle with Stoppab } class ReceiveMessageWithSameBehaviorSpec extends Messages { - override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor, StateA) -> null - private def behv(monitor: ActorRef[Event], state: State): Behavior[Command] = { - SBehaviors.setup[Command] { context => - SBehaviors - .receiveMessageWithSame[Command] { - case GetSelf => - monitor ! Self(context.self) - case Miss => - monitor ! Missed - case Ignore => - monitor ! Ignored - case Ping => - monitor ! Pong - behv(monitor, state) - case Swap => - monitor ! Swapped - behv(monitor, state.next) - case GetState() => - monitor ! state - case Stop => SBehaviors.stopped - case _: AuxPing => SBehaviors.unhandled - } - .receiveSignal { - case (_, signal) => - monitor ! ReceivedSignal(signal) - SBehaviors.same - } - } + override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor) -> null + private def behv(monitor: ActorRef[Event]): Behavior[Command] = { + SBehaviors + .receiveMessageWithSame[Command] { + case Miss => + monitor ! Missed + case Ignore => + monitor ! Ignored + case Ping => + monitor ! Pong + case _ => + } } } From 28a9ac690b35b6733734db9a305c0fe31737d6bf Mon Sep 17 00:00:00 2001 From: "Andy.Chen" Date: Tue, 27 Aug 2024 23:59:15 +0800 Subject: [PATCH 5/5] add @since annotation --- .../scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala | 2 ++ .../scala/org/apache/pekko/actor/typed/scaladsl/Behaviors.scala | 2 ++ 2 files changed, 4 insertions(+) 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 949afcd1656..c9d4facd350 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 @@ -157,6 +157,8 @@ object Behaviors { * Compared to using [[AbstractBehavior]] this factory is a more functional style * of defining the `Behavior`. Processing the next message will not result in * different behavior than this one + * + * @since 1.1.0 */ def receiveMessageWithSame[T](onMessage: pekko.japi.Procedure[T]): Behavior[T] = new BehaviorImpl.ReceiveBehavior((_, msg) => { 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 cbac507ccce..93c71616c78 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 @@ -147,6 +147,8 @@ object Behaviors { * Compared to using [[AbstractBehavior]] this factory is a more functional style * of defining the `Behavior`. Processing the next message will not result in * different behavior than this one + * + * @since 1.1.0 */ def receiveMessageWithSame[T](onMessage: T => Unit): Receive[T] = { new ReceiveMessageImpl(onMessage.andThen(_ => same))