diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/DispatchersDocTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/DispatchersDocTest.java new file mode 100644 index 0000000000..3614cf7dcb --- /dev/null +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/DispatchersDocTest.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 Lightbend Inc. + */ + +package jdocs.akka.typed; + +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.*; +import org.scalatest.junit.JUnitSuite; +import akka.actor.typed.DispatcherSelector; + +public class DispatchersDocTest { + + private static Behavior yourBehavior = Behaviors.empty(); + + private static Behavior example = Behaviors.receive((ctx, msg) -> { + + //#spawn-dispatcher + ctx.spawn(yourBehavior, "DefaultDispatcher"); + ctx.spawn(yourBehavior, "ExplicitDefaultDispatcher", DispatcherSelector.defaultDispatcher()); + ctx.spawn(yourBehavior, "BlockingDispatcher", DispatcherSelector.blocking()); + ctx.spawn(yourBehavior, "DispatcherFromConfig", DispatcherSelector.fromConfig("your-dispatcher")); + //#spawn-dispatcher + + return Behaviors.same(); + }); +} diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala new file mode 100644 index 0000000000..d16ec62cc5 --- /dev/null +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018 Lightbend Inc. + */ + +package docs.akka.typed + +import akka.actor.testkit.typed.scaladsl.{ ActorTestKit, TestProbe } +import akka.actor.typed.scaladsl.AskPattern._ +import akka.actor.typed.SpawnProtocol.Spawn +import akka.actor.typed.scaladsl.Behaviors +import akka.actor.typed.{ ActorRef, Behavior, SpawnProtocol, TypedAkkaSpecWithShutdown, Props, DispatcherSelector } +import akka.dispatch.Dispatcher +import org.scalatest.concurrent.ScalaFutures +import DispatchersDocSpec._ +import com.typesafe.config.{ Config, ConfigFactory } + +object DispatchersDocSpec { + + val config = ConfigFactory.parseString( + """ + //#config + your-dispatcher { + type = Dispatcher + executor = "thread-pool-executor" + thread-pool-executor { + fixed-pool-size = 32 + } + throughput = 1 + } + //#config + """.stripMargin) + + case class WhichDispatcher(replyTo: ActorRef[Dispatcher]) + + val giveMeYourDispatcher = Behaviors.receive[WhichDispatcher] { (ctx, msg) ⇒ + msg.replyTo ! ctx.executionContext.asInstanceOf[Dispatcher] + Behaviors.same + } + + val yourBehavior: Behavior[String] = Behaviors.same + + val example = Behaviors.receive[Any] { (ctx, msg) ⇒ + + //#spawn-dispatcher + import akka.actor.typed.DispatcherSelector + + ctx.spawn(yourBehavior, "DefaultDispatcher") + ctx.spawn(yourBehavior, "ExplicitDefaultDispatcher", DispatcherSelector.default()) + ctx.spawn(yourBehavior, "BlockingDispatcher", DispatcherSelector.blocking()) + ctx.spawn(yourBehavior, "DispatcherFromConfig", DispatcherSelector.fromConfig("your-dispatcher")) + //#spawn-dispatcher + + Behaviors.same + } + +} + +class DispatchersDocSpec extends ActorTestKit with TypedAkkaSpecWithShutdown with ScalaFutures { + + override def config: Config = DispatchersDocSpec.config + + "Actor Dispatchers" should { + "support default and blocking dispatcher" in { + val probe = TestProbe[Dispatcher]() + val actor: ActorRef[SpawnProtocol] = spawn(SpawnProtocol.behavior) + + val withDefault = (actor ? Spawn(giveMeYourDispatcher, "default", Props.empty)).futureValue + withDefault ! WhichDispatcher(probe.ref) + probe.expectMessageType[Dispatcher].id shouldEqual "akka.actor.default-dispatcher" + + val withBlocking = (actor ? Spawn(giveMeYourDispatcher, "default", DispatcherSelector.blocking())).futureValue + withBlocking ! WhichDispatcher(probe.ref) + probe.expectMessageType[Dispatcher].id shouldEqual "akka.actor.default-blocking-io-dispatcher" + + val withCustom = (actor ? Spawn(giveMeYourDispatcher, "default", DispatcherSelector.fromConfig("your-dispatcher"))).futureValue + withCustom ! WhichDispatcher(probe.ref) + probe.expectMessageType[Dispatcher].id shouldEqual "your-dispatcher" + } + } +} diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/Props.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/Props.scala index abbce37130..a87e2c1a4c 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/Props.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/Props.scala @@ -164,6 +164,12 @@ object DispatcherSelector { */ def defaultDispatcher(): DispatcherSelector = default() + /** + * Run the actor on the default blocking dispatcher that is + * configured under default-blocking-io-dispatcher + */ + def blocking(): DispatcherSelector = fromConfig("akka.actor.default-blocking-io-dispatcher") + /** * Look up an executor definition in the [[ActorSystem]] configuration. * ExecutorServices created in this fashion will be shut down when the diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/SpawnProtocol.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/SpawnProtocol.scala index ffe6e9e9dc..5fc4c86790 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/SpawnProtocol.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/SpawnProtocol.scala @@ -16,6 +16,12 @@ object SpawnProtocol { */ 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) } /** diff --git a/akka-docs/src/main/paradox/typed/dispatchers.md b/akka-docs/src/main/paradox/typed/dispatchers.md new file mode 100644 index 0000000000..4245d35dc2 --- /dev/null +++ b/akka-docs/src/main/paradox/typed/dispatchers.md @@ -0,0 +1,44 @@ +# Dispatchers + +## Dependency + +Dispatchers are part of core akka, which means that they are part of the akka-actor-typed dependency: + +@@dependency[sbt,Maven,Gradle] { + group="com.typesafe.akka" + artifact="akka-actor-typed_$scala.binary_version$" + version="$akka.version$" +} + +## Introduction + +An Akka `MessageDispatcher` is what makes Akka Actors "tick", it is the engine of the machine so to speak. +All `MessageDispatcher` implementations are also an @scala[`ExecutionContext`]@java[`Executor`], which means that they can be used +to execute arbitrary code, for instance @ref:[Futures](../futures.md). + +## Selecting a dispatcher + +A default dispatcher is used for all actors that are spawned without specifying a custom dispatcher. +This is suitable for all actors that don't block. Blocking in actors needs to be carefully managed, more +details @ref:[here](../dispatchers.md#blocking-needs-careful-management). + +To select a dispatcher use `DispatcherSelector` to create a `Props` instance for spawning your actor: + +Scala +: @@snip [DispatcherDocSpec.scala]($akka$/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala) { #spawn-dispatcher } + +Java +: @@snip [DispatcherDocTest.java]($akka$/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/DispatchersDocTest.java) { #spawn-dispatcher } + +`DispatcherSelector` has two convenience methods to look up the default dispatcher and a dispatcher you can use to +execute actors that block e.g. a legacy database API that does not support @scala[`Future`]@java[`CompletionStage`]s. + +The final example shows how to load a custom dispatcher from configuration and replies on this being in your application.conf: + +Scala +: @@snip [DispatcherDocSpec.scala]($akka$/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala) { #config } + +Java +: @@snip [DispatcherDocSpec.scala]($akka$/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala) { #config } + +For full details on how to configure custom dispatchers see the @ref:[untyped docs](../dispatchers.md#types-of-dispatchers). diff --git a/akka-docs/src/main/paradox/typed/index.md b/akka-docs/src/main/paradox/typed/index.md index 9b08a35457..000015491c 100644 --- a/akka-docs/src/main/paradox/typed/index.md +++ b/akka-docs/src/main/paradox/typed/index.md @@ -5,6 +5,7 @@ @@@ index * [actors](actors.md) +* [dispatchers](dispatchers.md) * [coexisting](coexisting.md) * [actor-lifecycle](actor-lifecycle.md) * [interaction patterns](interaction-patterns.md)