-
Notifications
You must be signed in to change notification settings - Fork 7
/
autostart.clj
52 lines (42 loc) · 1.48 KB
/
autostart.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
(ns mount.extensions.autostart
"This extension provides a `defstate` that auto-starts on first use.
Use `set-autostart-fn!` to configure which fn should be used to start the states."
(:require [mount.lite :as mount])
(:import [clojure.lang IDeref]
[mount.lite IState]))
(defonce
^{:doc "The fn that will be called to automatically start any state
that has been deref'd but not started. If this fn is unsuccessful
in starting the state, the standard error handling will occur."}
autostart-fn mount/start)
(defn set-autostart-fn!
"Configures `autostart-fn` use by `AutoStartState` during state deref."
[fn]
(alter-var-root #'autostart-fn (constantly fn)))
(defrecord AutoStartState [var state]
IState
(start* [_]
(mount/start* state))
(stop* [_]
(mount/stop* state))
(status* [_]
(mount/status* state))
(properties [_]
(mount/properties state))
IDeref
(deref [_]
(if (= :started (mount/status* state))
@state
;; synchronize access across thread boundaries just in case
;; two threads want to access/start this state at the same time.
(locking var
(autostart-fn var)
@state))))
(defmacro defstate
"Defines a state that will be auto-started on first deref, including its dependencies.
See `mount.lite/defstate` for more information."
[name & args]
`(do
(mount/defstate ~name ~@args)
(alter-var-root (var ~name) (fn [state#] (->AutoStartState (var ~name) state#)))
(var ~name)))