/ / Scala Play: Concurent.broadcast não funciona com EventSource - javascript, scala, playframework, playframework-2.0, server-sent-events

Scala Play: Concurent.broadcast não funciona com EventSource - javascript, scala, playframework, playframework-2.0, server-sent-events

Estou tendo problemas no Scala Play para conectar Conncurrent.broadcast com EventSource() para criar um bate-papo SSE funcional.

Este código abaixo não está funcionando.Tudo o que vejo são mensagens de depuração quando os usuários estão se conectando ao feed e isso é tudo. Nenhum dado está sendo enviado para os navegadores. E tenho certeza de que os dados foram enviados com sucesso para o servidor e enviados para chatChannel. O que há de errado? Como posso depurar isso?

val (chatOut, chatChannel) = Concurrent.broadcast[JsValue]

def postMessage = Action(parse.json) { req =>
chatChannel.push(req.body)
Ok
}

def chatFeed = Action { req =>
println("User connected to chat: " + req.remoteAddress)
Ok.chunked(chatOut
&> EventSource()
).as("text/event-stream")
}

Este código de depuração simples abaixo está funcionando e vejo os dados enviados do navegador, por meio chatChannel, no console, então esse lado está funcionando bem.

val (chatOut, chatChannel) = Concurrent.broadcast[JsValue]
val chatDebug = Iteratee.foreach[JsValue](m => println("Debug: " + m.toString))
chatOut |>>> chatDebug

def postMessage = Action(parse.json) { req =>
chatChannel.push(req.body)
Ok
}

E isso também está funcionando, e vejo strings aleatórias sendo enviadas ao navegador. Então a parte JS também está OK.

def chatFeed = Action { req =>
val producer = Enumerator.generateM[String](Promise.timeout(Some(Random.nextString(5)),3 second))
Ok.chunked(producer &> EventSource()).as("text/event-stream")
}

E de alguma forma, quando eu conecto essas duas partes, as mensagens não são transmitidas para o navegador.

Respostas:

1 para resposta № 1

Uau ! Eu estava pronto para desistir, mas descobri a origem do problema.

No routes arquivo, você usa o roteador de dependência injetada:

GET        /                    @controllers.Application.index
POST       /message             @controllers.Application.postMessage
GET        /feed                @controllers.Application.chatFeed

Usando o roteador estático (sem @ e o roteador padrão) funciona no seu exemplo:

GET        /                    @controllers.Application.index
POST       /message             controllers.Application.postMessage
GET        /feed                controllers.Application.chatFeed

De jogar doc:

O Play suporta a geração de dois tipos de roteadores,um é uma dependência roteador injetado, o outro é um roteador estático. O padrão é o roteador estático, mas se você criou um novo aplicativo Play usando o Jogue os modelos do ativador de sementes, seu projeto incluirá o seguinte configuração em build.sbt dizendo-lhe para usar o roteador injetado:

routesGenerator: = InjectedRoutesGenerator

Os exemplos de código na documentação do Play pressupõemque você está usando o gerador de rotas injetadas. Se você não estiver usando isso, você pode adaptar trivialmente os exemplos de código para o gerador de rotas estáticas, prefixando a parte de invocação do controlador da rota com um símbolo @, ou declarando cada um de seus controladores como um objeto em vez de uma aula.

Eu ainda não entendi muito bem a última frase já que o controlador não parece usar o gerador de rotas injetadas e, portanto, ter um @ deve usar o roteador estático