Pergunta

I use Play 2.2.2 with Scala. I have this code in my controller:

    def wsTest = WebSocket.using[JsValue] {
        implicit request =>
          val (out, channel) = Concurrent.broadcast[JsValue]
          val in = Iteratee.foreach[JsValue] {
            msg => println(msg)
          }
          userAuthenticatorRequest.tracked match { //detecting wheter the user is authenticated
            case Some(u) =>
              mySubscriber.start(u.id, channel)
            case _ =>
              channel push Json.toJson("{error: Sorry, you aren't authenticated yet}")
          }
          (in, out)
      }

calling this code:

object MySubscriber {

  def start(userId: String, channel: Concurrent.Channel[JsValue]) {
    ctx.getBean(classOf[ActorSystem]).actorOf(Props(classOf[MySubscriber], Seq("comment"), channel), name = "mySubscriber") ! "start"
    //a simple refresh would involve a duplication of this actor!
  }

}

class MySubscriber(redisChannels: Seq[String], channel: Concurrent.Channel[JsValue]) extends RedisSubscriberActor(new InetSocketAddress("localhost", 6379), redisChannels, Nil) with ActorLogging {

  def onMessage(message: Message) {
    println(s"message received: $message")
    channel.push(Json.parse(message.data))
  }

  override def onPMessage(pmessage: PMessage) {
    //not used
    println(s"message received: $pmessage")
  }
}

The problem is that when the user refreshes the page, then a new websocket restarts involving a duplication of Actors named mySubscriber.

I noticed that the Play's Java version has a way to detect a closed connection, in order to shutdown an actor. Example:

// When the socket is closed.
        in.onClose(new Callback0() {
           public void invoke() {
               // Shutdown the actor
               defaultRoom.shutdown();
           }
        });

How to handle the same thing with the Scala WebSocket API? I want to close the actor each time the socket is closed.

Foi útil?

Solução

As @Mik378 suggested, Iteratee.map serves the role of onClose.

val in = Iteratee.foreach[JsValue] {
  msg => println(msg)
} map { _ =>
  println("Connection has closed")
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top