A pure functional Scala MQTT client library
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 the lock-down days, around april 2020, to learn a lot about cats, cats effect 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 effect 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
- trying to consider Scala.js,
For examples on how to use it, you can have a look at the local subscriber or the local publisher code. The former is build using ZIO while the later is based on Cats Effect IO.
Artifacts are available at Sonatype OSS Repository Hosting service, even the
SNAPSHOTS are automatically
built by GitHub Actions. To include the Sonatype repositories in your SBT build you should add,
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 := "3.1.1" libraryDependencies ++= Seq( "net.sigusr" %% "fs2-mqtt" % "1.0.0" )
Roughly speaking this library depends on:
- Scala of course, but not Scala.js even thought this should be fairly easy…
- Cats effect
- scodec and scodec-stream
- Cats effects retry to manage connection attempts
It should work seamlessly with various compatible IO monads: Cats Effect IO
of course and ZIO as it supports cats effect typeclasses. Monix used to be supported as well, but
1.0.0 and the migration to cats effect
3.x, this is no more the case.
This work is licenced under an Apache Version 2.0 license