only create the routees once they can be looked-up, see #3406

- move the creation of the RoutedActorCell’s route into
  ActorCell.start(); it used to be done in the constructor
- this requires “val route” to turn into a volatile private var

Thanks to Patrik for finding it!
This commit is contained in:
Roland 2013-05-30 12:44:08 +02:00
parent 9c89f170d2
commit 0af123aa6d
3 changed files with 65 additions and 4 deletions

View file

@ -0,0 +1,51 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.routing
import akka.testkit.AkkaSpec
import akka.actor.Props
import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.LocalActorRef
import scala.concurrent.duration._
class RouteeCreationSpec extends AkkaSpec {
"Creating Routees" must {
"result in visible routees" in {
val N = 100
system.actorOf(Props(new Actor {
testActor ! system.actorFor(self.path)
def receive = Actor.emptyBehavior
}).withRouter(RoundRobinRouter(N)))
for (i 1 to N) {
expectMsgType[ActorRef] match {
case _: LocalActorRef // fine
case x fail(s"routee $i was a ${x.getClass}")
}
}
}
"allow sending to context.parent" in {
val N = 100
system.actorOf(Props(new Actor {
context.parent ! "one"
def receive = {
case "one" testActor forward "two"
}
}).withRouter(RoundRobinRouter(N)))
val gotit = receiveWhile(messages = N) {
case "two" lastSender.toString
}
expectNoMsg(100.millis)
if (gotit.size != N) {
fail(s"got only ${gotit.size} from \n${gotit mkString "\n"}")
}
}
}
}

View file

@ -74,7 +74,7 @@ private[akka] trait Dispatch { this: ActorCell ⇒
/**
* Start this cell, i.e. attach it to the dispatcher.
*/
final def start(): this.type = {
def start(): this.type = {
// This call is expected to start off the actor by scheduling its mailbox.
dispatcher.attach(this)
this

View file

@ -46,7 +46,7 @@ private[akka] object RoutedActorCell {
}
}
private[akka] class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActorRef, _props: Props, _supervisor: InternalActorRef)
private[akka] final class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActorRef, _props: Props, _supervisor: InternalActorRef)
extends ActorCell(
_system,
_ref,
@ -67,7 +67,11 @@ private[akka] class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActo
private var _routeeProvider: RouteeProvider = _
def routeeProvider = _routeeProvider
val route = {
@volatile
private var _route: Route = _
def route = _route
private def startRoute() {
val routeeProps = _props.withRouter(NoRouter)
_routeeProvider = routerConfig.createRouteeProvider(this, routeeProps)
val r = routerConfig.createRoute(routeeProvider)
@ -76,7 +80,13 @@ private[akka] class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActo
if (resizer.isTimeForResize(resizeCounter.getAndIncrement()))
resizer.resize(routeeProvider)
}
r
_route = r
}
override def start(): this.type = {
startRoute()
// create the routees before scheduling the Router actor
super.start()
}
/*