Late 2014, I initiated an MQTT client library for Scala side project. My purpose was to learn me some Akka while trying to deliver something potentially useful. I quickly found the excellent scodec library to encode/decode MQTT protocol frames, making this part of the work considerably easier, with a concise and very readable outcome.
More recently, while getting more and more interest in pure functional programming in Scala, in had the chance to see this amazing talk on Skunk from @tpolecat. It's about building, from the ground up, a data access library for Postgres based on FS2 and… scodec.
Oops!… I did it again.
I rushed to Skunk, which as been inspirational, and took the opportunity of these lock down days to learn a lot about cats, cats effects and of course FS2. I even found the integration between FS2 and scodec, scodec-stream, to be utterly useful.
With all these tools at hand, and the book Practical-FP in Scala: A hands-on approach on my desk, it has been quite (sic) easy to connect everything together and build this purely functional Scala MQTT client library.
This library is build in the tagless final style in order to make it, as much as possible, IO monad agnostic for the client code using it. It's internals are nevertheless mainly build around FS2, cats effetcs typeclasses and concurrency primitives.
It implements almost all the MQTT
3.1.1 protocol, managing (re)connections and in flight messages, and allows interacting with a Mosquitto broker. It does not support MQTT
5 and, to tell the truth, this is not even envisioned! Still, there's work ahead:
- finer grained configuration (e. g. number of in flight messages)
- a proper documentation
- shame on me, far more test coverage /o\
- performance evaluation
- cross builds would be nice… even considering Scala.js,
resolvers ++= Seq( Resolver.sonatypeRepo("releases"), Resolver.sonatypeRepo("snapshots") )
In case you want to easily give a try to this library, without the burden of adding resolvers, there is a release synced to Maven Central. In this case just add,
scalaVersion := "2.13.2" libraryDependencies ++= Seq( "net.sigusr" %% "fs2-mqtt" % "0.4.1" )
Roughly speaking this library depends on:
- Scala of course, but not Scala.js even thought this should be fairly easy…
- scodec and scodec-stream
- Cats effect for some internal concurrency stuff
- Cats effects retry to manage connection attempts
- Monocle… because why not!
This work is licenced under an Apache Version 2.0 license