2012-04-10 11 views
6

estoy modelando un P2P sencillo con Scala y Akka:Akka Actor "preguntar" y "aguardan" con TimeoutException

class Node() extends Peer with Actor { 

    var peers: List[ActorRef] = List() 

    def receive = { 
    case _register(peer: ActorRef, p: Option[Int]) => { 
     println("registering [" + peer + "] for [" + this + "]") 
     peers = peer :: peers 
    } 
    } 

} 

sealed case class _register(val peer: ActorRef, var p: Option[Int] = None) 

y luego una red simple:

class Network() extends Actor { 

    def this(name: String) = { 

    this() 

    val system = ActorSystem(name) 

    val s1 = system.actorOf(Props(new Node()), name = "s1") 
    val s2 = system.actorOf(Props(new Node()), name = "s2") 

    val c1 = system.actorOf(Props(new Node()), name = "c1") 
    val c2 = system.actorOf(Props(new Node()), name = "c2") 
    val c3 = system.actorOf(Props(new Node()), name = "c3") 
    val c4 = system.actorOf(Props(new Node()), name = "c4") 

    implicit val timeout = Timeout(5 second) 

    s1 ? _register(c1) 
    s1 ? _register(c2) 
    s1 ? _register(c3) 
    val lastRegistered = s2 ? _register(c4) 
    Await.ready(lastRegistered, timeout.duration) 

    println("initialized nodes") 
    } 
} 

La salida que yo estoy poniendo es siempre como:

registering [Actor[akka://p2p/user/c1]] for [[email protected]] 
registering [Actor[akka://p2p/user/c2]] for [[email protected]] 
registering [Actor[akka://p2p/user/c3]] for [[email protected]] 
registering [Actor[akka://p2p/user/c4]] for [[email protected]] 
[ERROR] [04/10/2012 22:07:04.34] [main-akka.actor.default-dispatcher-1] [akka://main/user/p2p] error while creating actor 
java.util.concurrent.TimeoutException: Futures timed out after [5000] milliseconds 
    at akka.dispatch.DefaultPromise.ready(Future.scala:834) 
    at akka.dispatch.DefaultPromise.ready(Future.scala:811) 
    at akka.dispatch.Await$.ready(Future.scala:64) 
    at nl.cwi.crisp.examples.p2p.scala.Network.<init>(Node.scala:136) 
    at nl.cwi.crisp.examples.p2p.scala.Main$$anonfun$11.apply(Node.scala:164) 
    at nl.cwi.crisp.examples.p2p.scala.Main$$anonfun$11.apply(Node.scala:164) 
    at akka.actor.ActorCell.newActor(ActorCell.scala:488) 
    at akka.actor.ActorCell.create$1(ActorCell.scala:506) 
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:591) 
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:191) 
    at akka.dispatch.Mailbox.run(Mailbox.scala:160) 
    at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:505) 
    at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259) 
    at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:997) 
    at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1495) 
    at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104) 

he seguido la documentación de Futures en la documentación de referencia Akka. El intercambio de Await.ready con Await.result no tiene ningún efecto. El registro muestra que el último registro ha sido exitoso.

¿Cómo puedo solucionar esto?

Respuesta

8

Usted está esperando un mensaje a devolver del actor nodo, pero el actor nodo no envía un mensaje de vuelta a la sender actorRef, por lo que el futuro [Cualquier] creado por s1 ? _register nunca recibirán una respuesta, por lo que la El futuro nunca estará completo. Puede agregar sender ! something desde dentro del método Node receive para enviar una respuesta, no estoy seguro de qué tiene sentido en este caso something.

+1

Gracias, eso fue un error descuidado! '¡remitente! Ninguno' funcionaría para mí. – nobeh

8

guiso lo tiene razón, pero usted tiene algún código preocupante en su actor de la red:

val system = ActorSystem(name) 

val s1 = system.actorOf(Props(new Node()), name = "s1") 
val s2 = system.actorOf(Props(new Node()), name = "s2") 

val c1 = system.actorOf(Props(new Node()), name = "c1") 
val c2 = system.actorOf(Props(new Node()), name = "c2") 
val c3 = system.actorOf(Props(new Node()), name = "c3") 
val c4 = system.actorOf(Props(new Node()), name = "c4") 

Por qué estás creando una nueva ActorSystem, y por qué estás creando actores de alto nivel dentro de ese sistema el actor ?

Si necesita acceder al sistema del actor, simple llamada:

context.system 

Y usted debe evitar la creación de actores de primer nivel "porque sí", por la misma razón que usted no debe estorbar la raíz de su sistema de archivos colocando todos sus archivos allí. Para crear niños-actores a la red, acaba de hacer:

context.actorOf(...) 

Ahora usted tiene un problema tan pronto como se crea más de una Red-actor en el mismo sistema, ya que intentará crear la parte superior actores de nivel del mismo nombre.

+1

Gracias por los consejos claros. – nobeh

+1

Eres muy bienvenido. Happy hAkking! –

Cuestiones relacionadas