Skip to content
A chat server implemented using WebSockets and Scala/http4s
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
project
src Remove Circe dependency, rename server class Apr 8, 2019
static
.gitignore
.travis.yml
LICENSE
README.md
build.sbt

README.md

http4s-chatserver Build Status

A chat server implemented using WebSockets and http4s. Note that the version of this project mimics http4s itself, so the tags on the project indicate what versions this example has been built against. It was initially developed against 0.20.0-M6.

A working demo of this project is available here: https://martinsnyder.net/projects/chat.html.

This project is a practical example of:

  • How to work with WebSockets in http4s
  • Implementing application state using fs2 streams
  • The publish/subscribe pattern

Messages are processed as follows:

In ChatRoutes (processInput)

  1. Message received via WebSocket
  2. Message text parsed into InputMessage
  3. InputMessage routed to Queue

In ChatServer (processingStream)

  1. Queued InputMessages pumped through the current ChatState, producing a "next" state and some number of OutputMessage objects.
  2. "Next" state is managed by a functional mutable reference (Ref)
  3. OutputMessage objects are routed to a topic (publish/subscribe pattern)

In ChatRoutes (toClient)

  1. OutputMessage objects are received from the topic
  2. User-specific filter is applied to the stream
  3. Message text is routed to the WebSocket

Notes

Concurrency in fs2

This implementation relies heavily on the concurrency objects Ref, Queue and Topic. They are used both to move messages between streams and also to control the flow of messages in general.

A more complicated implementation would queue on a per-room basis. That would require per-room queues though, and would distract from what this example is trying to demonstrate.

Limitations

The biggest weakness of what I've done here is that all traffic is routed through a single queue. This neutralizes many of the benefits of http4s. Queueing is necessary in this case because we need to sequence our messages in order to conduct the state transformations on ChatState. A more complicated model would use multiple queues (and potentially multiple state objects), perhaps along room boundaries.

Functional enhancements

Functional improvements to this application can be implemented by modifying InputMessage, OutputMessage and ChatState. These three classes are vanilla Scala and have no fs2 or http4s dependencies. That means that 100% of the functionality can be trivially unit-tested or evaluated in the REPL by a novice Scala programmer.

Further reading

You can’t perform that action at this time.