Behavior.orElse start the other behavior (#25977)

* Behavior.orElse start the other behavior
* Finalize the case classes
This commit is contained in:
Christopher Batey 2018-12-05 10:10:48 +00:00 committed by GitHub
parent e9fb3a020a
commit f1b9adb0c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 10 deletions

View file

@ -6,14 +6,16 @@ package akka.actor.typed
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.testkit.typed.scaladsl._
import org.scalatest.Matchers
import org.scalatest.WordSpec
import org.scalatest.{ Matchers, WordSpec, WordSpecLike }
object OrElseStubbedSpec {
object OrElseSpec {
sealed trait Ping
case class Ping1(replyTo: ActorRef[Pong]) extends Ping
case class Ping2(replyTo: ActorRef[Pong]) extends Ping
case class Ping3(replyTo: ActorRef[Pong]) extends Ping
final case class Ping1(replyTo: ActorRef[Pong]) extends Ping
final case class Ping2(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)
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 {
@ -71,6 +73,88 @@ class OrElseSpec extends WordSpec with Matchers {
testkit.run(Ping1(inbox.ref))
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))
}
}

View file

@ -6,8 +6,8 @@ package akka.actor.typed
import akka.actor.InvalidMessageException
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.WrappingBehavior
import akka.util.{ LineNumbers, OptionVal }
@ -51,7 +51,9 @@ sealed abstract class Behavior[T] { 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))
}
}
/**

View file

@ -65,6 +65,7 @@ import akka.actor.typed.scaladsl.{ ActorContext ⇒ SAC }
InterceptorImpl(interceptor, behavior)
class OrElseBehavior[T](first: Behavior[T], second: Behavior[T]) extends ExtensibleBehavior[T] {
override def receive(ctx: AC[T], msg: T): Behavior[T] = {
Behavior.interpretMessage(first, ctx, msg) match {
case _: UnhandledBehavior.type Behavior.interpretMessage(second, ctx, msg)

View file

@ -11,6 +11,7 @@ import java.util.concurrent.TimeUnit
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.Promise
import scala.concurrent.duration._
import akka.Done
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit