Search code examples
scalawebsocketakka-streamakka-http

how can I inject a keep-alive into a websocket handler in akka-http?


I've written some code to communicate with a browser over websockets using akka-http 10.0.9. It works nicely, except that the connection times out. Although we're sending a constant stream of data to the client, the client isn't requesting anything for long periods of time.

I know the solution is to inject keep-alive messages into the incoming websocket source, like this:

val s = Source(List(data....)).keepAlive(15.seconds, () => Strict.TextMessage("heart beat"))

However, the akka-http api calls for a flow to handle the connection:

path("query") {
        parameter('session, 'package) {
          (session,packageId) =>
            val sg = getGraphManager(session)
            sg match {
              case Left(error) => complete(StatusCodes.BadRequest -> TSError(msg=error))
              case Right(gm) =>
                val tsFlow = new TSFlow(ksource, session)
                handleWebSocketMessages(Flow.fromGraph(tsFlow.flowGraph))

            }
         }
 }

Consequently, I never see the incoming source, so there's no opportunity to inject the keep-alive. How should I restructure things so I can inject a keep-alive?


Solution

  • The only way to control how connections are dropped server-side is to change the idle-timeout (see the docs here and here).

    You can set

    idle-timeout = infinite
    

    to completely disable the timeout.

    If you want to use keep alive messages, they need to be sent from the client side. The .keepAlive combinator is the easiest way to get them if your client is based on Akka Streams.