Two-Way Websocket Messaging with Akka

Ryan Miville
2 min readOct 22, 2017

--

I’ve recently been working on Akkord, a Scala library for writing chatbots for my messaging app of choice, Discord. I specifically made the decision to rely on Akka modules as much as practically possible, since I knew I wanted to model my bots as actors and I wanted more experience with the other Akka modules.

One of my first hurdles was implementing the Discord Websocket API which requires the client to reply to connection and heartbeat messages from the server. I knew it had to be possible with Akka, but for the life of me I could not find a straightforward tutorial that covered this particular use case. By piecing together ideas from Colin Breck’s excellent blog series, I was able to accomplish my task and I am rather happy with how it reads. So without further ado, let’s get started!

Websocket Ping Pong

In order to give you the tutorial I was looking for, rather than connecting to a Discord server, we’ll extrapolate the classic Akka ping pong example. But instead of our actor receiving messages directly, we will communicate with a remote server via a Websocket.

Note: This isn’t a real server. I made it up for the example.

We managed to cram Akka actors, HTTP, and streams in a 30 line gist. Not bad, eh? Now let’s go over some of the pieces that might not be so self evident.

If you are familiar with Akka streams, you’ll recall that back-pressure is a core concept. In order to use an actor as a Sink, we have to specify explicit replies for stream initialization, completion, and notifying the upstream Flow that our actor is ready to process more messages. These are our Init, Complete, and Ack respectively.

You’ll notice the way our actor replies to server messages is by offering a message to aqueue. This is the materialized value of Source.queue[T]. For this example, we’ve just initialized our Source with a buffer size of Int.MaxValue and OverflowStrategy.backpressure. Explore the other strategies and consider what is right for your application before simply copying the above settings.

Next Steps and Gotchas

The combination of Source.queue with Sink.actorRefWithAck is the key to two-way communication via Websockets with Akka. One caveat as described by Colin Breck is that queue can only be used from one thread. If that is an issue for you, I fear you‘ll have a little more work ahead of you to synchronize those calls. However, if you do not need to have several threads sending messages over the same websocket connection, then you’re in luck and the above code should prove helpful.

For a little more complex example, take a look at Akkord, and in particular the WebsocketConnectionBehavior trait. Feel free to play around with the library and add issues as well if you’d like. Please keep in mind that it is still in development and not ready for high volume bots.

--

--

Ryan Miville

Software engineer with an interest in functional and reactive programming, modern architecture, and developer productivity