Commit d3dabc94 authored by Will Billingsley's avatar Will Billingsley
Browse files

Made one of the websocket examples more idiomatic

parent 70d8eeb1
......@@ -87,7 +87,7 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
*
* @return
*/
def websocketWithHelper():WebSocket = {
def webSocketWithHelper():WebSocket = {
WebSocketHelper.createWebSocket[String, String](
{ queue =>
// We now have an asynchronous queue. What would we like to do with it
......@@ -109,39 +109,44 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
* asynchronous work. However, using this template, you should just
* @return
*/
def websocket() = WebSocket.accept[String, String] { request =>
// Our source is going to be an asynchronous queue we can push messages to with 'out.offer(msg)'. This is going to
// be the "source" of our flow. A complication is it doesn't create the queue immediately - this just says
// *when* this source is connected to a flow, create a queue. So we don't have a queue yet.
val outSource = Source.queue[String](50, OverflowStrategy.backpressure)
def webSocket() = WebSocket.accept[String, String] { request =>
// Because I want to refer to the queue in the sink, but I haven't actually got the queue yet, I'm just creating
// a box to put our queue in. At the moment, it's empty
var outOpt:Option[SourceQueueWithComplete[String]] = None
// Create a "sink" that describes what we want to do with each message. Here, I'm just going to count the characters
// and echo it straight back out on the "out" queue.
val in = Sink.foreach[String] { message =>
// A websocket is made from a "flow" - a source of messages up to the browser, and a sink for messages from the browser.
// We're going to need to give this function our Sink and our Source as arguments.
Flow.fromSinkAndSourceCoupledMat(
// If we have an out queue, send the message on it
outOpt foreach { out =>
out.offer(s"That message had ${message.length} characters in it")
}
// Create a "sink" that describes what we want to do with each message. Here, I'm just going to count the characters
// and echo it straight back out on the "out" queue.
Sink.foreach[String] { message =>
}
// If we have an out queue, send the message on it
outOpt foreach { out =>
out.offer(s"That message had ${message.length} characters in it")
}
},
// This defines a "flow" -- something that has an input and an output.
// "Coupled" means that if the input closes, the output will close
// "Mat" means "materialised" -- ie, it'll give us the output queue that gets created and the Future that will
// complete when the flow is done.
Flow.fromSinkAndSourceCoupledMat(in, outSource) { case (done, out) =>
// Our source is going to be an asynchronous queue we can push messages to with 'out.offer(msg)'.
// The queue will be created when the connection is complete - this just says what it *will* be
Source.queue[String](50, OverflowStrategy.backpressure)
// done is a future that will complete when the flow finishes
) { case (done, queue) =>
// the second argument list is a callback that takes a tuple with two arguments.
// done is a future (like a JavaScript promise) that will complete when the flow finishes
// out is our "materialised" output queue. All we need do is put it in the box we made earlier
out.offer("Connected!")
outOpt = Some(out)
// Send a connected message to the browser
queue.offer("Connected!")
// Put the queue in the box we defined earlier
outOpt = Some(queue)
// When the connection has ended, empty the box and println that it's closed
done.foreach { _ =>
outOpt = None
println("Connection closed!")
......@@ -149,6 +154,7 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
}
}
/**
......
......@@ -11,8 +11,8 @@ POST /example/json controllers.ExamplesController.receiveJsonPo
GET /example/game controllers.ExamplesController.game(id:Option[String])
GET /example/socket controllers.ExamplesController.websocket()
GET /example/time controllers.ExamplesController.websocketWithHelper()
GET /example/socket controllers.ExamplesController.webSocket()
GET /example/time controllers.ExamplesController.webSocketWithHelper()
GET /example/eventsource controllers.ExamplesController.eventSource()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment