2012-04-10 12 views
13

Estoy implementando un sondeo largo en Play 2.0 en un entorno potencialmente distribuido. La forma en que lo entiendo es que cuando Play obtiene una solicitud, debe suspender la notificación pendiente de una actualización y luego ir a la base de datos para buscar nuevos datos y repetir. Empecé a buscar el ejemplo de chat que ofrece Play 2.0, pero está en websocket. Además, no parece que pueda distribuirse. Así que pensé que usaría el bus de eventos de Akka. Tomé la implementación de eventstream y dupliqué la mía con LookupClassification. Sin embargo, no estoy seguro de cómo voy a recibir un mensaje de vuelta (o, para el caso, ¿cuál debería ser el suscriptor en lugar de ActorRef)?Implementando un sondeo largo en scala y play 2.0 con akka

aplicación EVENTSTREAM: https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/event/EventStream.scala

Respuesta

5

No estoy seguro de que eso es lo que busca, pero no hay una solución bastante simple en la muestra cometa-reloj, que puede adaptarse a usar actores AKKA. Utiliza un iframe infinito en lugar de un largo sondeo. He utilizado una versión adaptada para una aplicación más compleja haciendo múltiples llamadas a bases de datos y cálculos largos en AKKA actores y funciona bien.

def enum = Action { 
    //get your actor 
    val myActorRef = Akka.system.actorOf(Props[TestActor]) 

    //do some query to your DB here. Promise.timeout is to simulate a blocking call 
    def getDatabaseItem(id: Int): Promise[String] = { Promise.timeout("test", 10 milliseconds) } 

    //test iterator, you will want something smarter here 
    val items1 = 1 to 10 toIterator 

    // this is a very simple enumerator that takes ints from an existing iterator (for an http request parameters for instance) and do some computations 
    def myEnum(it: Iterator[Int]): Enumerator[String] = Enumerator.fromCallback[String] {() => 
     if (!items1.hasNext) 
     Promise.pure[Option[String]](None) //we are done with our computations 
     else { 

     // get the next int, query the database and compose the promise with a further query to the AKKA actor 
     getDatabaseItem(items1.next).flatMap { dbValue => 
      implicit val timeout = new Timeout(10 milliseconds) 
      val future = (myActorRef ? dbValue) mapTo manifest[String] 

      // here we convert the AKKA actor to the right Promise[Option] output 
      future.map(v => Some(v)).asPromise 
     } 
     } 
    } 

    // finally we stream the result to the infinite iframe. 
    // console.log is the javascript callback, you will want something more interesting. 
    Ok.stream(myEnum(items1) &> Comet(callback = "console.log")) 
    } 

Tenga en cuenta que este fromCallback no permite que usted combine con enumeradores "andthen", existe en la versión maletero de un método play2 generateM que podría ser más apropiado si desea utilizar combinaciones.

No es un largo sondeo, pero funciona bien.

1

Me tropecé con su pregunta mientras buscaba lo mismo.

he encontrado la solución de streaming poco satisfactoria, ya que causaron "ruleta de la muerte" en el navegador WebKit (es decir, muestra que se está cargando todo el tiempo)

De todos modos, no tenía ninguna suerte para encontrar buenos ejemplos, pero me las arreglé para crear mi propia prueba de concepto usando promesas: https://github.com/kallebertell/longpoll

Cuestiones relacionadas