Skip to content

Commit

Permalink
store readme
Browse files Browse the repository at this point in the history
  • Loading branch information
source-c committed Nov 3, 2022
1 parent 631a360 commit dff015d
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
= MQTT broker for Clojure

== Rationale

Unfortunately there are few to nothing libraries natively suitable to be used in Clojure development that implement MQTT server side functionalities.

The Moquette library is Java MQTT broker based on an eventing model with Netty. The library has a good performance and is desegned with embedding support out of the box. Its configuration is compatible with well known Mosquitto Open Source MQTT server.

Being combained together there and empowered by Clojure - these tools open the way to painless M2M communications for services written in Clojure.

== Compatibility

The following implementations are successfully passes production tests:

- Moquette
- Mosquitto
- Paho
- MQTT.js
- DKD/Brownie

== Usage

The usage pattern is simple:

- define handlers
- create broker instance
- start the service
- serve messages

=== Defining handlers

The handlers record should implement `InterceptHandler` interface

[source, clojure]
----
(defrecord BasicHandler [id]
InterceptHandler
(onPublish [_ msg]
(let [payload (-> msg .getPayload (.toString StandardCharsets/UTF_8))]
(log/info "Received on topic: " + (.getTopicName msg) + " content: " + payload)))
(getID [_] id)
(getInterceptedMessageTypes [_] InterceptHandler/ALL_MESSAGE_TYPES))
----

The full set of method to be overrided:

. onPublish
. onConnect
. onDisconnect
. onConnectionLost
. onSubscribe
. onUnsubscribe
. onMessageAcknowledged
. getID
. getInterceptedMessageTypes

The `ALL_MESSAGE_TYPES` vector contains the whole bunch of the related messages types.

=== Creating instance

The library contains default `SimpleBroker` implementation written in Java that requires resources' configuration file name to be passed into construtor.

In order to manage the instance itnshould be passed as a parameter into the Clojure record implements `CljBroker` interface.

.CljBroker interface definition
[source, clojure]
----
(defprotocol CljBroker
(start [o ^InterceptHandler handlers])
(open [o ^InterceptHandler handlers])
(stop [o])
(close [o])
(send [o from to data qos retain?]))
----

so the instantiation of the complete Broker is looks like:

[source, clojure]
----
(def config-name "my-broker-settings.conf")
(def srv-java (SimpleBroker. config-name))
(def srv-clj (Broker. srv-java))
----

=== Starting the service

The clojure interface support two approaches:

. controling the instance by calling `start`/`stop` methods (that fully corresponds to its Java interface)
. controling the instance by `with-open` macro

.start/stop
[source,clojure]
----
...
(let [srv (Broker. (SimpleBroker. config-name))]
(start srv (BasicHandler. "My Instance"))
;; your code here
(stop srv))
...
----

.with-open
[source,clojure]
----
...
(with-open [srv (Broker. (SimpleBroker. config-name))]
(start srv (BasicHandler. "My Instance")))
;; or even
(def config-name "my-broker-settings.conf")
(def srv-java (SimpleBroker. config-name))
(def srv-clj (Broker. srv-java))
(with-open [srv (open srv-clj (BasicHandler. "My Instance"))]
(comment "Do your stuff here"))
----

== License

© 2022 Fern Flower Lab

Distributed under the MIT License.

0 comments on commit dff015d

Please sign in to comment.