+doc #15537 add Typed router pattern

Conflicts:
	akka-docs/rst/scala/code/docs/persistence/PersistenceDocSpec.scala
This commit is contained in:
Konrad 'ktoso' Malawski 2014-07-14 14:51:09 +02:00
parent 76bc8afe8c
commit ba2411833a
5 changed files with 205 additions and 24 deletions

View file

@ -3,14 +3,15 @@
*/
package docs.actor
import language.postfixOps
import scala.concurrent.{ Promise, Future, Await }
import scala.concurrent.duration._
import akka.actor.{ ActorContext, TypedActor, TypedProps }
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
import org.scalatest.Matchers
import java.lang.String.{ valueOf => println }
import akka.actor.{ ActorContext, ActorRef, TypedActor, TypedProps }
import akka.routing.RoundRobinGroup
import akka.testkit._
import scala.concurrent.{ Future, Await }
import scala.concurrent.duration._
//Mr funny man avoids printing to stdout AND keeping docs alright
import java.lang.String.{ valueOf => println }
import akka.actor.ActorRef
@ -62,6 +63,19 @@ trait Bar {
class FooBar extends Foo with Bar
//#typed-actor-supercharge
//#typed-router-types
trait HasName {
def name(): String
}
class Named extends HasName {
import scala.util.Random
private val id = Random.nextInt(1024)
def name(): String = "name-" + id
}
//#typed-router-types
class TypedActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"get the TypedActor extension" in {
@ -181,4 +195,31 @@ class TypedActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
//#typed-actor-supercharge-usage
Await.result(f, 3 seconds) should be("YES")
}
"typed router pattern" in {
//#typed-router
def namedActor(): HasName = TypedActor(system).typedActorOf(TypedProps[Named]())
// prepare routees
val routees: List[HasName] = List.fill(5) { namedActor() }
val routeePaths = routees map { r =>
TypedActor(system).getActorRefFor(r).path.toStringWithoutAddress
}
// prepare untyped router
val router: ActorRef = system.actorOf(RoundRobinGroup(routeePaths).props())
// prepare typed proxy, forwarding MethodCall messages to `router`
val typedRouter: HasName =
TypedActor(system).typedActorOf(TypedProps[Named](), actorRef = router)
println("actor was: " + typedRouter.name()) // name-184
println("actor was: " + typedRouter.name()) // name-753
println("actor was: " + typedRouter.name()) // name-320
println("actor was: " + typedRouter.name()) // name-164
//#typed-router
routees foreach { TypedActor(system).poisonPill(_) }
TypedActor(system).poisonPill(router)
}
}

View file

@ -214,3 +214,21 @@ Here's an example on how you can use traits to mix in behavior in your Typed Act
.. includecode:: code/docs/actor/TypedActorDocSpec.scala#typed-actor-supercharge
.. includecode:: code/docs/actor/TypedActorDocSpec.scala#typed-actor-supercharge-usage
Typed Router pattern
--------------------
Sometimes you want to spread messages between multiple actors. The easiest way to achieve this in Akka is to use a :ref:`Router <routing-scala>`,
which can implement a specific routing logic, such as ``smallest-mailbox`` or ``consistent-hashing`` etc.
Routers are not provided directly for typed actors, but it is really easy to leverage an untyped router and use a typed proxy in front of it.
To showcase this let's create typed actors that assign themselves some random ``id``, so we know that in fact, the router has sent the message to different actors:
.. includecode:: code/docs/actor/TypedActorDocSpec.scala#typed-router-types
In order to round robin among a few instances of such actors, you can simply create a plain untyped router,
and then facade it with a ``TypedActor`` like shown in the example below. This works because typed actors of course
communicate using the same mechanisms as normal actors, and methods calls on them get transformed into message sends of ``MethodCall`` messages.
.. includecode:: code/docs/actor/TypedActorDocSpec.scala#typed-router