Align SpawnProtocol with style guide #27318
This commit is contained in:
parent
511356177d
commit
d03294d359
8 changed files with 67 additions and 60 deletions
|
|
@ -31,20 +31,21 @@ public class SpawnProtocolDocTest {
|
|||
public abstract static class HelloWorldMain {
|
||||
private HelloWorldMain() {}
|
||||
|
||||
public static final Behavior<SpawnProtocol> main =
|
||||
public static final Behavior<SpawnProtocol.Command> main =
|
||||
Behaviors.setup(
|
||||
context -> {
|
||||
// Start initial tasks
|
||||
// context.spawn(...)
|
||||
|
||||
return SpawnProtocol.behavior();
|
||||
return SpawnProtocol.create();
|
||||
});
|
||||
}
|
||||
// #main
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// #system-spawn
|
||||
final ActorSystem<SpawnProtocol> system = ActorSystem.create(HelloWorldMain.main, "hello");
|
||||
final ActorSystem<SpawnProtocol.Command> system =
|
||||
ActorSystem.create(HelloWorldMain.main, "hello");
|
||||
final Duration timeout = Duration.ofSeconds(3);
|
||||
|
||||
CompletionStage<ActorRef<HelloWorld.Greet>> greeter =
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import akka.actor.typed.scaladsl.Behaviors
|
|||
import akka.util.Timeout
|
||||
import org.scalatest.{ Matchers, WordSpec, WordSpecLike }
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
object SpawnProtocolSpec {
|
||||
sealed trait Message
|
||||
final case class Ping(replyTo: ActorRef[Pong.type]) extends Message
|
||||
|
|
@ -32,7 +34,7 @@ class SpawnProtocolSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
"Spawn behavior" must {
|
||||
"spawn child actor" in {
|
||||
val parentReply = TestProbe[ActorRef[Message]]()
|
||||
val parent = spawn(SpawnProtocol.behavior, "parent")
|
||||
val parent = spawn(SpawnProtocol(), "parent")
|
||||
parent ! SpawnProtocol.Spawn(target, "child", Props.empty, parentReply.ref)
|
||||
val child = parentReply.receiveMessage()
|
||||
child.path.name should ===("child")
|
||||
|
|
@ -43,17 +45,18 @@ class SpawnProtocolSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
}
|
||||
|
||||
"have nice API for ask" in {
|
||||
val parent = spawn(SpawnProtocol.behavior, "parent2")
|
||||
val parent = spawn(SpawnProtocol(), "parent2")
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
implicit val timeout = Timeout(5.seconds)
|
||||
val parentReply = parent.ask(SpawnProtocol.Spawn(target, "child", Props.empty))
|
||||
val parentReply: Future[ActorRef[Ping]] =
|
||||
parent.ask(SpawnProtocol.Spawn(target, "child", Props.empty, _))
|
||||
val child = parentReply.futureValue
|
||||
val childReply = TestProbe[Pong.type]()
|
||||
child ! Ping(childReply.ref)
|
||||
}
|
||||
|
||||
"be possible to use as guardian behavior" in {
|
||||
val sys = ActorSystem(SpawnProtocol.behavior, "SpawnProtocolSpec2")
|
||||
val sys = ActorSystem(SpawnProtocol(), "SpawnProtocolSpec2")
|
||||
try {
|
||||
val guardianReply = TestProbe[ActorRef[Message]]()(sys)
|
||||
sys ! SpawnProtocol.Spawn(target, "child1", Props.empty, guardianReply.ref)
|
||||
|
|
@ -70,7 +73,7 @@ class SpawnProtocolSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
|
||||
"spawn with unique name when given name is taken" in {
|
||||
val parentReply = TestProbe[ActorRef[Message]]()
|
||||
val parent = spawn(SpawnProtocol.behavior, "parent3")
|
||||
val parent = spawn(SpawnProtocol(), "parent3")
|
||||
|
||||
parent ! SpawnProtocol.Spawn(target, "child", Props.empty, parentReply.ref)
|
||||
val child0 = parentReply.receiveMessage()
|
||||
|
|
@ -101,7 +104,7 @@ class StubbedSpawnProtocolSpec extends WordSpec with Matchers {
|
|||
|
||||
"spawn with given name" in {
|
||||
val parentReply = TestInbox[ActorRef[Message]]()
|
||||
val testkit = BehaviorTestKit(SpawnProtocol.behavior)
|
||||
val testkit = BehaviorTestKit(SpawnProtocol())
|
||||
testkit.run(SpawnProtocol.Spawn(target, "child", Props.empty, parentReply.ref))
|
||||
val child = parentReply.receiveMessage()
|
||||
child.path.name should ===("child")
|
||||
|
|
@ -110,7 +113,7 @@ class StubbedSpawnProtocolSpec extends WordSpec with Matchers {
|
|||
|
||||
"spawn anonymous when name undefined" in {
|
||||
val parentReply = TestInbox[ActorRef[Message]]()
|
||||
val testkit = BehaviorTestKit(SpawnProtocol.behavior)
|
||||
val testkit = BehaviorTestKit(SpawnProtocol())
|
||||
testkit.run(SpawnProtocol.Spawn(target, "", Props.empty, parentReply.ref))
|
||||
val child = parentReply.receiveMessage()
|
||||
child.path.name should startWith("$")
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class DispatcherSelectorSpec extends ScalaTestWithActorTestKit(DispatcherSelecto
|
|||
}
|
||||
|
||||
"select same dispatcher as parent" in {
|
||||
val parent = spawn(SpawnProtocol.behavior, Props.empty.withDispatcherFromConfig("ping-pong-dispatcher"))
|
||||
val parent = spawn(SpawnProtocol(), Props.empty.withDispatcherFromConfig("ping-pong-dispatcher"))
|
||||
val childProbe = createTestProbe[ActorRef[Ping]]()
|
||||
parent ! SpawnProtocol.Spawn(PingPong(), "child", Props.empty.withDispatcherSameAsParent, childProbe.ref)
|
||||
|
||||
|
|
@ -68,10 +68,10 @@ class DispatcherSelectorSpec extends ScalaTestWithActorTestKit(DispatcherSelecto
|
|||
}
|
||||
|
||||
"select same dispatcher as parent, several levels" in {
|
||||
val grandParent = spawn(SpawnProtocol.behavior, Props.empty.withDispatcherFromConfig("ping-pong-dispatcher"))
|
||||
val grandParent = spawn(SpawnProtocol(), Props.empty.withDispatcherFromConfig("ping-pong-dispatcher"))
|
||||
val parentProbe = createTestProbe[ActorRef[SpawnProtocol.Spawn[Ping]]]()
|
||||
grandParent ! SpawnProtocol.Spawn(
|
||||
SpawnProtocol.behavior,
|
||||
SpawnProtocol(),
|
||||
"parent",
|
||||
Props.empty.withDispatcherSameAsParent,
|
||||
parentProbe.ref)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
|||
import com.typesafe.config.ConfigFactory
|
||||
import org.scalatest.WordSpecLike
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
object DispatchersDocSpec {
|
||||
|
||||
val config = ConfigFactory.parseString("""
|
||||
|
|
@ -60,19 +62,22 @@ class DispatchersDocSpec extends ScalaTestWithActorTestKit(DispatchersDocSpec.co
|
|||
"Actor Dispatchers" should {
|
||||
"support default and blocking dispatcher" in {
|
||||
val probe = TestProbe[Dispatcher]()
|
||||
val actor: ActorRef[SpawnProtocol] = spawn(SpawnProtocol.behavior)
|
||||
val actor: ActorRef[SpawnProtocol.Command] = spawn(SpawnProtocol())
|
||||
|
||||
val withDefault = actor.ask(Spawn(giveMeYourDispatcher, "default", Props.empty)).futureValue
|
||||
withDefault ! WhichDispatcher(probe.ref)
|
||||
val withDefault: Future[ActorRef[WhichDispatcher]] =
|
||||
actor.ask(Spawn(giveMeYourDispatcher, "default", Props.empty, _))
|
||||
withDefault.futureValue ! WhichDispatcher(probe.ref)
|
||||
probe.receiveMessage().id shouldEqual "akka.actor.default-dispatcher"
|
||||
|
||||
val withBlocking = actor.ask(Spawn(giveMeYourDispatcher, "default", DispatcherSelector.blocking())).futureValue
|
||||
withBlocking ! WhichDispatcher(probe.ref)
|
||||
val withBlocking: Future[ActorRef[WhichDispatcher]] =
|
||||
actor.ask(Spawn(giveMeYourDispatcher, "default", DispatcherSelector.blocking(), _))
|
||||
withBlocking.futureValue ! WhichDispatcher(probe.ref)
|
||||
probe.receiveMessage().id shouldEqual "akka.actor.default-blocking-io-dispatcher"
|
||||
|
||||
val withCustom =
|
||||
actor.ask(Spawn(giveMeYourDispatcher, "default", DispatcherSelector.fromConfig("your-dispatcher"))).futureValue
|
||||
withCustom ! WhichDispatcher(probe.ref)
|
||||
val withCustom: Future[ActorRef[WhichDispatcher]] =
|
||||
actor.ask(Spawn(giveMeYourDispatcher, "default", DispatcherSelector.fromConfig("your-dispatcher"), _))
|
||||
|
||||
withCustom.futureValue ! WhichDispatcher(probe.ref)
|
||||
probe.receiveMessage().id shouldEqual "your-dispatcher"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ object SpawnProtocolDocSpec {
|
|||
|
||||
//#main
|
||||
object HelloWorldMain {
|
||||
val main: Behavior[SpawnProtocol] =
|
||||
val main: Behavior[SpawnProtocol.Command] =
|
||||
Behaviors.setup { context =>
|
||||
// Start initial tasks
|
||||
// context.spawn(...)
|
||||
|
||||
SpawnProtocol.behavior
|
||||
SpawnProtocol()
|
||||
}
|
||||
}
|
||||
//#main
|
||||
|
|
@ -51,7 +51,7 @@ class SpawnProtocolDocSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
"be able to spawn actors" in {
|
||||
//#system-spawn
|
||||
|
||||
val system: ActorSystem[SpawnProtocol] =
|
||||
val system: ActorSystem[SpawnProtocol.Command] =
|
||||
ActorSystem(HelloWorldMain.main, "hello")
|
||||
|
||||
// needed in implicit scope for ask (?)
|
||||
|
|
@ -61,7 +61,7 @@ class SpawnProtocolDocSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
implicit val scheduler: Scheduler = system.scheduler
|
||||
|
||||
val greeter: Future[ActorRef[HelloWorld.Greet]] =
|
||||
system.ask(SpawnProtocol.Spawn(behavior = HelloWorld(), name = "greeter", props = Props.empty))
|
||||
system.ask(SpawnProtocol.Spawn(behavior = HelloWorld(), name = "greeter", props = Props.empty, _))
|
||||
|
||||
val greetedBehavior = Behaviors.receive[HelloWorld.Greeted] { (context, message) =>
|
||||
context.log.info("Greeting for {} from {}", message.whom, message.from)
|
||||
|
|
@ -69,7 +69,7 @@ class SpawnProtocolDocSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
|||
}
|
||||
|
||||
val greetedReplyTo: Future[ActorRef[HelloWorld.Greeted]] =
|
||||
system.ask(SpawnProtocol.Spawn(greetedBehavior, name = "", props = Props.empty))
|
||||
system.ask(SpawnProtocol.Spawn(greetedBehavior, name = "", props = Props.empty, _))
|
||||
|
||||
for (greeterRef <- greeter; replyToRef <- greetedReplyTo) {
|
||||
greeterRef ! HelloWorld.Greet("Akka", replyToRef)
|
||||
|
|
|
|||
|
|
@ -5,25 +5,29 @@
|
|||
package akka.actor.typed
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import akka.annotation.DoNotInherit
|
||||
|
||||
/**
|
||||
* A message protocol for actors that support spawning a child actor when receiving a [[SpawnProtocol#Spawn]]
|
||||
* message and sending back the [[ActorRef]] of the child actor. Create instances through the [[SpawnProtocol#apply]]
|
||||
* or [[SpawnProtocol.create()]] factory methods.
|
||||
*
|
||||
* The typical usage of this is to use it as the guardian actor of the [[ActorSystem]], possibly combined with
|
||||
* `Behaviors.setup` to starts some initial tasks or actors. Child actors can then be started from the outside
|
||||
* by telling or asking [[SpawnProtocol#Spawn]] to the actor reference of the system. When using `ask` this is
|
||||
* similar to how [[akka.actor.ActorSystem#actorOf]] can be used in untyped actors with the difference that
|
||||
* a `Future` / `CompletionStage` of the `ActorRef` is returned.
|
||||
*
|
||||
* Stopping children is done through specific support in the protocol of the children, or stopping the entire
|
||||
* spawn protocol actor.
|
||||
*/
|
||||
object SpawnProtocol {
|
||||
|
||||
object Spawn {
|
||||
|
||||
/**
|
||||
* Special factory to make using Spawn with ask easier
|
||||
*/
|
||||
def apply[T](behavior: Behavior[T], name: String, props: Props): ActorRef[ActorRef[T]] => Spawn[T] =
|
||||
replyTo => new Spawn(behavior, name, props, replyTo)
|
||||
|
||||
/**
|
||||
* Special factory to make using Spawn with ask easier. Props defaults to Props.empty
|
||||
*/
|
||||
def apply[T](behavior: Behavior[T], name: String): ActorRef[ActorRef[T]] => Spawn[T] =
|
||||
replyTo => new Spawn(behavior, name, Props.empty, replyTo)
|
||||
}
|
||||
/**
|
||||
* Not for user extension
|
||||
*/
|
||||
@DoNotInherit sealed trait Command
|
||||
|
||||
/**
|
||||
* Spawn a child actor with the given `behavior` and send back the `ActorRef` of that child to the given
|
||||
|
|
@ -37,12 +41,17 @@ object SpawnProtocol {
|
|||
* `InvalidActorNameException`, but it's better to use unique names to begin with.
|
||||
*/
|
||||
final case class Spawn[T](behavior: Behavior[T], name: String, props: Props, replyTo: ActorRef[ActorRef[T]])
|
||||
extends SpawnProtocol
|
||||
extends Command
|
||||
|
||||
/**
|
||||
* Behavior implementing the [[SpawnProtocol]].
|
||||
* Java API: returns a behavior that can be commanded to spawn arbitrary children.
|
||||
*/
|
||||
val behavior: Behavior[SpawnProtocol] =
|
||||
def create(): Behavior[Command] = apply()
|
||||
|
||||
/**
|
||||
* Scala API: returns a behavior that can be commanded to spawn arbitrary children.
|
||||
*/
|
||||
def apply(): Behavior[Command] =
|
||||
Behaviors.receive { (ctx, msg) =>
|
||||
msg match {
|
||||
case Spawn(bhvr, name, props, replyTo) =>
|
||||
|
|
@ -67,17 +76,3 @@ object SpawnProtocol {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A message protocol for actors that support spawning a child actor when receiving a [[SpawnProtocol#Spawn]]
|
||||
* message and sending back the [[ActorRef]] of the child actor. An implementation of a behavior for this
|
||||
* protocol is defined in [[SpawnProtocol#behavior]]. That can be used as is or composed with other behavior
|
||||
* using [[Behavior#orElse]].
|
||||
*
|
||||
* The typical usage of this is to use it as the guardian actor of the [[ActorSystem]], possibly combined with
|
||||
* `Behaviors.setup` to starts some initial tasks or actors. Child actors can then be started from the outside
|
||||
* by telling or asking [[SpawnProtocol#Spawn]] to the actor reference of the system. When using `ask` this is
|
||||
* similar to how [[akka.actor.ActorSystem#actorOf]] can be used in untyped actors with the difference that
|
||||
* a `Future` / `CompletionStage` of the `ActorRef` is returned.
|
||||
*/
|
||||
sealed abstract class SpawnProtocol
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package akka.cluster.typed.internal
|
|||
import akka.actor.testkit.typed.scaladsl.TestProbe
|
||||
import akka.actor.typed.ActorRef
|
||||
import akka.actor.typed.Behavior
|
||||
import akka.actor.typed.Props
|
||||
import akka.actor.typed.SpawnProtocol
|
||||
import akka.actor.typed.receptionist.Receptionist
|
||||
import akka.actor.typed.receptionist.ServiceKey
|
||||
|
|
@ -54,11 +55,11 @@ abstract class ClusterReceptionistUnreachabilitySpec
|
|||
|
||||
import ClusterReceptionistUnreachabilitySpec._
|
||||
|
||||
val spawnActor = system.actorOf(PropsAdapter(SpawnProtocol.behavior)).toTyped[SpawnProtocol]
|
||||
val spawnActor = system.actorOf(PropsAdapter(SpawnProtocol())).toTyped[SpawnProtocol.Command]
|
||||
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = {
|
||||
implicit val timeout: Timeout = 3.seconds
|
||||
implicit val scheduler = typedSystem.scheduler
|
||||
val f: Future[ActorRef[T]] = spawnActor.ask(ref => SpawnProtocol.Spawn(behavior, name)(ref))
|
||||
val f: Future[ActorRef[T]] = spawnActor.ask(SpawnProtocol.Spawn(behavior, name, Props.empty, _))
|
||||
|
||||
Await.result(f, 3.seconds)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -462,6 +462,8 @@ made before finalizing the APIs. Compared to Akka 2.5.x the source incompatible
|
|||
`interceptMessageType` method in `BehaviorInterceptor` is replaced with this @scala[`ClassTag`]@java[`Class`] parameter.
|
||||
* `Behavior.orElse` has been removed because it wasn't safe together with `narrow`.
|
||||
* `StashBuffer`s are now created with `Behaviors.withStash` rather than instantiating directly
|
||||
* To align with the Akka Typed style guide `SpawnProtocol` is now created through @scala[`SpawnProtocol()`]@java[`SpawnProtocol.create()`], the special `Spawn` message
|
||||
factories has been removed and the top level of the actor protocol is now `SpawnProtocol.Command`
|
||||
|
||||
#### Akka Typed Stream API changes
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue