Chapter 10. Immutant Daemons
Daemons are long-running services sharing the lifecycle of your application. Their chief benefit is as a highly available "singleton" service in a cluster of Immutants.
10.2. Starting a Daemon
The primary abstraction is the
Daemon protocol, which prescribes
stop. Daemon instances are passed to the
immutant.daemons/create function along with a name. A JMX MBean
is then created and started asynchronously. The stop function is
automatically invoked when your application is undeployed.
A convenience function, immutant.daemons/daemonize, may be used to encapsulate the creation of a Daemon from two functions. It takes three parameters:
name- a name for referencing as a JMX MBean
start- a start function to be invoked asynchronously
stop- a stop function that will be automatically invoked when your app is undeployed, providing a hook to cleanly teardown resources used by the daemon
In addition, the following options are supported:
|:singleton||Singleton daemons will only execute on one node in a cluster. If false, the daemon will run on every node.|
:singleton option only applies when deployed to a
cluster. Immutant provides automatic failover for singleton daemons:
should it crash, the daemon will be automatically started on another
node chosen at random, resulting in a robust, highly-available
The following contrived examples show a simple mechanism for controlling a daemon via a shared atom.
First, using the Daemon protocol directly:
(ns example.init (:require [immutant.daemons :as daemon])) ;; Controls the state of our daemon (def done (atom false)) ;; An implementation of Daemon (defrecord Service  daemon/Daemon (start [_] (reset! done false) (loop [i 0] (Thread/sleep 1000) (when-not @done (println i) (recur (inc i))))) (stop [_] (reset! done true))) ;; Register the daemon (daemon/create "mydaemon" (Service.) :singleton true)
And alternatively, passing two functions:
(ns example.init (:require [immutant.daemons :as daemon]) ;; Controls the state of our daemon (def done (atom false)) ;; Our daemon's start function (defn start  (reset! done false) (loop [i 0] (Thread/sleep 1000) (when-not @done (do-something) (recur (inc i))))) ;; Our daemon's stop function (defn stop  (reset! done true)) ;; Register the daemon (daemon/daemonize "mydaemon" start stop :singleton false)