playframework / playframework

The Community Maintained High Velocity Web Framework For Java and Scala.
http://www.playframework.com
Apache License 2.0
12.55k stars 4.1k forks source link

Outdated doc for Websockets #6408

Open note opened 8 years ago

note commented 8 years ago

Play Version (2.5.4)

API (Scala)

Operating System (MacOS 10.11)

Hello, I try to get familiar with WebSockets in Play. I am following https://www.playframework.com/documentation/2.5.x/ScalaWebSockets#closing-a-websocket. After a few hours wasted I found out that this doc is probably outdated. In current Play you close Websocket connection by closing underlying akka-stream. Would be great if you can update docs accordingly.

Probably you don't need a reproducer because I feel it's expected behavior, but just in case:

Expected Behavior

  1. after sending PoisonPill connection is getting closed

    Actual Behavior

after sending PoisonPill connection is not getting closed. I base that on:

  1. my client's callback onclose is not fired,
  2. Chrome's network Tab shows WS connection as Pending

    Reproducible Test Case

you can see this code at https://github.com/note/play-ws-example, here's what is essential for this case: https://github.com/note/play-ws-example/blob/master/app/controllers/WebSocketController.scala. I also included my JS code here: https://github.com/note/play-ws-example/tree/master/client

wsargent commented 8 years ago

@note will take a look at this, but did you find the example project at https://github.com/playframework/play-websocket-scala useful?

justgook commented 8 years ago

have totally same issue, and https://github.com/playframework/play-websocket-scala didn't help, cannot find some clear way how to close connection, for now im using, in websocket actor

  override def postStop() = {
    context.parent ! PoisonPill 
   }

but in such way, i cannot send some message, before I close connection, and create some kind of timeout is not really good solution

note commented 8 years ago

@wsargent https://github.com/playframework/play-websocket-scala is generally useful but not in case when you want to handle Websocket with Actor (as opposed to Flow).

@justgook you need to complete underlying Flow. I don't know your use case - providing that switching from Actor to Flow is not easy you can use KillSwitch. You can read about them here: http://doc.akka.io/docs/akka/2.4/scala/stream/stream-dynamic.html. The point is to connect introduced by you initial Flow with your actor using via method. Then if you have KillSwitch to initial Flow you can pass it as parameter to Actor. Then Actor can decide about closing the Flow.

schmitch commented 8 years ago

A lot of people might just need something like the old concurrent Channel:

https://gist.github.com/schmitch/8474d9fe4b0bd39849a026f437a52617

With that you can terminate every WebSocket via the complete() method of the backing queue. Basically you don't need to use any Actor to handle your WebSockets. probably when you spawn multiple Clients you shouldn't use "simple" Actors or a normal Source anyway. So without reading and learning the Akka-Streams doc you can't have a client spawning over multiple servers.

wsargent commented 8 years ago

Now that Hub support is in Akka 2.4.10 http://doc.akka.io/docs/akka/current/scala/stream/stream-dynamic.html#Dynamic_fan-in_and_fan-out_with_MergeHub_and_BroadcastHub we should revisit https://github.com/playframework/play-websocket-scala as much of the actor stuff is there essentially as a hub shim...