Behavior.orElse start the other behavior (#25977)
* Behavior.orElse start the other behavior * Finalize the case classes
This commit is contained in:
parent
e9fb3a020a
commit
f1b9adb0c4
4 changed files with 98 additions and 10 deletions
|
|
@ -6,14 +6,16 @@ package akka.actor.typed
|
||||||
|
|
||||||
import akka.actor.typed.scaladsl.Behaviors
|
import akka.actor.typed.scaladsl.Behaviors
|
||||||
import akka.actor.testkit.typed.scaladsl._
|
import akka.actor.testkit.typed.scaladsl._
|
||||||
import org.scalatest.Matchers
|
import org.scalatest.{ Matchers, WordSpec, WordSpecLike }
|
||||||
import org.scalatest.WordSpec
|
|
||||||
|
object OrElseStubbedSpec {
|
||||||
|
|
||||||
object OrElseSpec {
|
|
||||||
sealed trait Ping
|
sealed trait Ping
|
||||||
case class Ping1(replyTo: ActorRef[Pong]) extends Ping
|
final case class Ping1(replyTo: ActorRef[Pong]) extends Ping
|
||||||
case class Ping2(replyTo: ActorRef[Pong]) extends Ping
|
final case class Ping2(replyTo: ActorRef[Pong]) extends Ping
|
||||||
case class Ping3(replyTo: ActorRef[Pong]) extends Ping
|
final case class Ping3(replyTo: ActorRef[Pong]) extends Ping
|
||||||
|
final case class PingInfinite(replyTo: ActorRef[Pong]) extends Ping
|
||||||
|
|
||||||
case class Pong(counter: Int)
|
case class Pong(counter: Int)
|
||||||
|
|
||||||
def ping(counters: Map[String, Int]): Behavior[Ping] = {
|
def ping(counters: Map[String, Int]): Behavior[Ping] = {
|
||||||
|
|
@ -45,9 +47,9 @@ object OrElseSpec {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrElseSpec extends WordSpec with Matchers {
|
class OrElseStubbedSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
import OrElseSpec._
|
import OrElseStubbedSpec._
|
||||||
|
|
||||||
"Behavior.orElse" must {
|
"Behavior.orElse" must {
|
||||||
|
|
||||||
|
|
@ -71,6 +73,88 @@ class OrElseSpec extends WordSpec with Matchers {
|
||||||
testkit.run(Ping1(inbox.ref))
|
testkit.run(Ping1(inbox.ref))
|
||||||
inbox.receiveMessage() should ===(Pong(3))
|
inbox.receiveMessage() should ===(Pong(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrElseSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
||||||
|
|
||||||
|
import OrElseStubbedSpec._
|
||||||
|
|
||||||
|
"Behavior.orElse" must {
|
||||||
|
"work for deferred behavior on the left" in {
|
||||||
|
val orElseDeferred = Behaviors.setup[Ping] { _ ⇒
|
||||||
|
Behaviors.receiveMessage { _ ⇒
|
||||||
|
Behaviors.unhandled
|
||||||
|
}
|
||||||
|
}.orElse(ping(Map.empty))
|
||||||
|
|
||||||
|
val p = spawn(orElseDeferred)
|
||||||
|
val probe = TestProbe[Pong]
|
||||||
|
p ! Ping1(probe.ref)
|
||||||
|
probe.expectMessage(Pong(1))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"work for deferred behavior on the right" in {
|
||||||
|
val orElseDeferred = ping(Map.empty).orElse(Behaviors.setup { _ ⇒
|
||||||
|
Behaviors.receiveMessage {
|
||||||
|
case PingInfinite(replyTo) ⇒
|
||||||
|
replyTo ! Pong(-1)
|
||||||
|
Behaviors.same
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val p = spawn(orElseDeferred)
|
||||||
|
val probe = TestProbe[Pong]
|
||||||
|
p ! PingInfinite(probe.ref)
|
||||||
|
probe.expectMessage(Pong(-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"handle nested OrElse" in {
|
||||||
|
|
||||||
|
sealed trait Parent
|
||||||
|
final case class Add(o: Any) extends Parent
|
||||||
|
final case class Remove(o: Any) extends Parent
|
||||||
|
final case class Stack(s: ActorRef[Array[StackTraceElement]]) extends Parent
|
||||||
|
final case class Get(s: ActorRef[Set[Any]]) extends Parent
|
||||||
|
|
||||||
|
def dealer(set: Set[Any]): Behavior[Parent] = {
|
||||||
|
val add = Behaviors.receiveMessage[Parent] {
|
||||||
|
case Add(o) ⇒ dealer(set + o)
|
||||||
|
case _ ⇒ Behaviors.unhandled
|
||||||
|
}
|
||||||
|
val remove = Behaviors.receiveMessage[Parent] {
|
||||||
|
case Remove(o) ⇒ dealer(set - o)
|
||||||
|
case _ ⇒ Behaviors.unhandled
|
||||||
|
}
|
||||||
|
val getStack = Behaviors.receiveMessagePartial[Parent] {
|
||||||
|
case Stack(sender) ⇒
|
||||||
|
sender ! Thread.currentThread().getStackTrace
|
||||||
|
Behaviors.same
|
||||||
|
}
|
||||||
|
val getSet = Behaviors.receiveMessagePartial[Parent] {
|
||||||
|
case Get(sender) ⇒
|
||||||
|
sender ! set
|
||||||
|
Behaviors.same
|
||||||
|
}
|
||||||
|
add.orElse(remove).orElse(getStack).orElse(getSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = spawn(dealer(Set.empty))
|
||||||
|
|
||||||
|
(0 to 10000) foreach { i ⇒
|
||||||
|
y ! Add(i)
|
||||||
|
}
|
||||||
|
(0 to 9999) foreach { i ⇒
|
||||||
|
y ! Remove(i)
|
||||||
|
}
|
||||||
|
val probe = TestProbe[Set[Any]]
|
||||||
|
y ! Get(probe.ref)
|
||||||
|
probe.expectMessage(Set[Any](10000))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ package akka.actor.typed
|
||||||
|
|
||||||
import akka.actor.InvalidMessageException
|
import akka.actor.InvalidMessageException
|
||||||
import akka.actor.typed.internal.BehaviorImpl
|
import akka.actor.typed.internal.BehaviorImpl
|
||||||
import scala.annotation.tailrec
|
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
import akka.actor.typed.internal.BehaviorImpl.OrElseBehavior
|
import akka.actor.typed.internal.BehaviorImpl.OrElseBehavior
|
||||||
import akka.actor.typed.internal.WrappingBehavior
|
import akka.actor.typed.internal.WrappingBehavior
|
||||||
import akka.util.{ LineNumbers, OptionVal }
|
import akka.util.{ LineNumbers, OptionVal }
|
||||||
|
|
@ -51,7 +51,9 @@ sealed abstract class Behavior[T] { behavior ⇒
|
||||||
*
|
*
|
||||||
* @param that the fallback `Behavior`
|
* @param that the fallback `Behavior`
|
||||||
*/
|
*/
|
||||||
final def orElse(that: Behavior[T]): Behavior[T] = new OrElseBehavior[T](this, that)
|
final def orElse(that: Behavior[T]): Behavior[T] = Behavior.DeferredBehavior[T] { ctx ⇒
|
||||||
|
new OrElseBehavior[T](Behavior.start(this, ctx), Behavior.start(that, ctx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ import akka.actor.typed.scaladsl.{ ActorContext ⇒ SAC }
|
||||||
InterceptorImpl(interceptor, behavior)
|
InterceptorImpl(interceptor, behavior)
|
||||||
|
|
||||||
class OrElseBehavior[T](first: Behavior[T], second: Behavior[T]) extends ExtensibleBehavior[T] {
|
class OrElseBehavior[T](first: Behavior[T], second: Behavior[T]) extends ExtensibleBehavior[T] {
|
||||||
|
|
||||||
override def receive(ctx: AC[T], msg: T): Behavior[T] = {
|
override def receive(ctx: AC[T], msg: T): Behavior[T] = {
|
||||||
Behavior.interpretMessage(first, ctx, msg) match {
|
Behavior.interpretMessage(first, ctx, msg) match {
|
||||||
case _: UnhandledBehavior.type ⇒ Behavior.interpretMessage(second, ctx, msg)
|
case _: UnhandledBehavior.type ⇒ Behavior.interpretMessage(second, ctx, msg)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import java.util.concurrent.TimeUnit
|
||||||
import scala.concurrent.ExecutionContext
|
import scala.concurrent.ExecutionContext
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
import scala.concurrent.Promise
|
import scala.concurrent.Promise
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
import akka.Done
|
import akka.Done
|
||||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue