2012-04-10 10 views
13

Sto implementando il polling lungo in Play 2.0 in un ambiente potenzialmente distribuito. Il modo in cui capisco è che quando Play riceve una richiesta, dovrebbe sospendere la notifica in attesa di un aggiornamento, quindi andare al db per recuperare nuovi dati e ripetere. Ho iniziato a guardare l'esempio di chat che offre Play 2.0 ma è in websocket. Inoltre, non sembra che sia in grado di essere distribuito. Quindi ho pensato di utilizzare il bus eventi di Akka. Ho preso l'implementazione di eventi e ho replicato il mio con LookupClassification. Tuttavia sono perplesso su come recuperare un messaggio (o per quello che dovrebbe essere l'abbonato invece di ActorRef)?Implementazione di polling lungo in scala e riproduzione 2.0 con akka

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

risposta

5

io non sono sicuro che è quello che state cercando, ma c'è piuttosto una soluzione semplice nel campione cometa orologio, che si può adattare a utilizzare attori AKKA. Usa un iframe infinito anziché un lungo polling. Ho usato una versione adattata per un'applicazione più complessa che fa più chiamate DB e calcolo lungo negli attori AKKA e funziona perfettamente.

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")) 
    } 

Si noti che questo fromCallback non consente di combinare enumeratori con "andthen", v'è nella versione tronco di play2 un metodo generateM che potrebbe essere più appropriato se si desidera utilizzare combinazioni.

Non è un polling lungo, ma funziona correttamente.

1

Mi sono imbattuto nella tua domanda mentre cercavo la stessa cosa.

ho trovato la soluzione di streaming insoddisfacente in quanto hanno causato "filatrice della morte" in del browser webkit (cioè mostra si sta caricando tutto il tempo)

In ogni caso, non ha avuto alcuna fortuna trovare buoni esempi, ma sono riuscito a creare il mio proof-of-concept usando le promesse: https://github.com/kallebertell/longpoll