[#20] lifecycle fns take fns and values
This commit is contained in:
parent
9be822b2e9
commit
1c970e152a
12 changed files with 51 additions and 47 deletions
26
README.md
26
README.md
|
|
@ -79,16 +79,16 @@ mount is an alternative to the [component](https://github.com/stuartsierra/compo
|
|||
Creating state is easy:
|
||||
|
||||
```clojure
|
||||
(defstate conn :start (create-conn))
|
||||
(defstate conn :start create-conn)
|
||||
```
|
||||
|
||||
where `(create-conn)` is defined elsewhere, can be right above it.
|
||||
where the `create-conn` function is defined elsewhere, can be right above it.
|
||||
|
||||
In case this state needs to be cleaned / destryed between reloads, there is also `:stop`
|
||||
|
||||
```clojure
|
||||
(defstate conn :start (create-conn)
|
||||
:stop (disconnect conn))
|
||||
(defstate conn :start create-conn
|
||||
:stop #(disconnect conn))
|
||||
```
|
||||
|
||||
That is pretty much it. But wait, there is more.. this state is _a top level being_, which means it can be simply
|
||||
|
|
@ -101,6 +101,14 @@ dev=> conn
|
|||
#object[datomic.peer.LocalConnection 0x1661a4eb "datomic.peer.LocalConnection@1661a4eb"]
|
||||
```
|
||||
|
||||
#### Value of values
|
||||
|
||||
Lifecycle functions start/stop/suspend/resume can take both functions and values. This is valuable and also works:
|
||||
|
||||
```clojure
|
||||
(mount/defstate answer-to-the-ultimate-question-of-life-the-universe-and-everything :start 42)
|
||||
```
|
||||
|
||||
### Using State
|
||||
|
||||
For example let's say an `app` needs a connection above. No problem:
|
||||
|
|
@ -136,7 +144,7 @@ There are of course direct dependecies that `mount` respects:
|
|||
(:require [mount.core :refer [defstate]]))
|
||||
|
||||
(defstate app-config
|
||||
:start (load-config "test/resources/config.edn"))
|
||||
:start #(load-config "test/resources/config.edn"))
|
||||
```
|
||||
|
||||
this `app-config`, being top level, can be used in other namespaces, including the ones that create states:
|
||||
|
|
@ -146,7 +154,7 @@ this `app-config`, being top level, can be used in other namespaces, including t
|
|||
(:require [mount.core :refer [defstate]]
|
||||
[app.config :refer [app-config]]))
|
||||
|
||||
(defstate conn :start (create-connection app-config))
|
||||
(defstate conn :start #(create-connection app-config))
|
||||
```
|
||||
|
||||
[here](https://github.com/tolitius/mount/blob/master/test/app/nyse.clj)
|
||||
|
|
@ -310,9 +318,9 @@ and some other use cases.
|
|||
In additiong to `start` / `stop` functions, a state can also have `resume` and, if needed, `suspend` ones:
|
||||
|
||||
```clojure
|
||||
(defstate web-server :start (start-server ...)
|
||||
:resume (resume-server ...)
|
||||
:stop (stop-server ...))
|
||||
(defstate web-server :start #(start-server ...)
|
||||
:resume #(resume-server ...)
|
||||
:stop #(stop-server ...))
|
||||
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ Depending on the number of application components the "extra" size may vary.
|
|||
Mount is pretty much:
|
||||
|
||||
```clojure
|
||||
(defstate name :start (fn)
|
||||
:stop (fn))
|
||||
(defstate name :start fn
|
||||
:stop fn)
|
||||
```
|
||||
|
||||
no "ceremony".
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
# Introduction to statuo
|
||||
|
||||
TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)
|
||||
|
|
@ -63,8 +63,8 @@ For the example sake the app reads arguments in two places:
|
|||
* [inside](https://github.com/tolitius/mount/blob/with-args/test/app/nyse.clj#L17) a `defstate`
|
||||
|
||||
```clojure
|
||||
(defstate conn :start (new-connection (mount/args))
|
||||
:stop (disconnect (mount/args) conn))
|
||||
(defstate conn :start #(new-connection (mount/args))
|
||||
:stop #(disconnect (mount/args) conn))
|
||||
```
|
||||
|
||||
* and from "any" [other place](https://github.com/tolitius/mount/blob/with-args/test/app/config.clj#L8) within a function:
|
||||
|
|
@ -84,13 +84,13 @@ In order to demo all of the above, we'll build an uberjar:
|
|||
```bash
|
||||
$ lein do clean, uberjar
|
||||
...
|
||||
Created .. mount/target/mount-0.2.0-SNAPSHOT-standalone.jar
|
||||
Created .. mount/target/mount-0.1.5-SNAPSHOT-standalone.jar
|
||||
```
|
||||
|
||||
Since we have a default for a Datomic URI, it'll work with no arguments:
|
||||
|
||||
```bash
|
||||
$ java -jar target/mount-0.2.0-SNAPSHOT-standalone.jar
|
||||
$ java -jar target/mount-0.1.5-SNAPSHOT-standalone.jar
|
||||
|
||||
22:12:03.290 [main] INFO mount - >> starting.. app-config
|
||||
22:12:03.293 [main] INFO mount - >> starting.. conn
|
||||
|
|
@ -101,7 +101,7 @@ $ java -jar target/mount-0.2.0-SNAPSHOT-standalone.jar
|
|||
Now let's ask it to help us:
|
||||
|
||||
```bash
|
||||
$ java -jar target/mount-0.2.0-SNAPSHOT-standalone.jar --help
|
||||
$ java -jar target/mount-0.1.5-SNAPSHOT-standalone.jar --help
|
||||
|
||||
22:13:48.798 [main] INFO mount - >> starting.. app-config
|
||||
22:13:48.799 [main] INFO app.config -
|
||||
|
|
@ -116,7 +116,7 @@ this is a sample mount app to demo how to pass and read runtime arguments
|
|||
And finally let's connect to the Single Malt Database. It's Friday..
|
||||
|
||||
```bash
|
||||
$ java -jar target/mount-0.2.0-SNAPSHOT-standalone.jar -d datomic:mem://single-malt-database
|
||||
$ java -jar target/mount-0.1.5-SNAPSHOT-standalone.jar -d datomic:mem://single-malt-database
|
||||
|
||||
22:16:10.733 [main] INFO mount - >> starting.. app-config
|
||||
22:16:10.737 [main] INFO mount - >> starting.. conn
|
||||
|
|
|
|||
|
|
@ -38,15 +38,14 @@ where `nyse-app` is _the_ app. It has the usual routes:
|
|||
and the reloadable state:
|
||||
|
||||
```clojure
|
||||
(defn start-nyse []
|
||||
(create-nyse-schema) ;; creating schema (usually done long before the app is started..)
|
||||
(defn start-nyse [{:keys [www]}]
|
||||
(-> (routes mount-example-routes)
|
||||
(handler/site)
|
||||
(run-jetty {:join? false
|
||||
:port (get-in app-config [:www :port])})))
|
||||
:port (:port www)})))
|
||||
|
||||
(defstate nyse-app :start (start-nyse)
|
||||
:stop (.stop nyse-app)) ;; it's a "org.eclipse.jetty.server.Server" at this point
|
||||
(defstate nyse-app :start #(start-nyse app-config)
|
||||
:stop #(.stop nyse-app)) ;; it's a "org.eclipse.jetty.server.Server" at this point
|
||||
```
|
||||
|
||||
In order not to block, and being reloadable, the Jetty server is started in the "`:join? false`" mode which starts the server,
|
||||
|
|
|
|||
|
|
@ -35,16 +35,16 @@
|
|||
(validate lifecycle)
|
||||
(let [s-meta (cond-> {:mount-state mount-state
|
||||
:order (make-state-seq state)
|
||||
:start `(fn [] (~@start))
|
||||
:start `(fn [] ~start)
|
||||
:started? false}
|
||||
stop (assoc :stop `(fn [] (~@stop)))
|
||||
suspend (assoc :suspend `(fn [] (~@suspend)))
|
||||
resume (assoc :resume `(fn [] (~@resume))))]
|
||||
stop (assoc :stop `(fn [] ~stop))
|
||||
suspend (assoc :suspend `(fn [] ~suspend))
|
||||
resume (assoc :resume `(fn [] ~resume)))]
|
||||
`(defonce ~(with-meta state (merge (meta state) s-meta))
|
||||
(NotStartedState. ~(str state))))))
|
||||
|
||||
(defn- record! [{:keys [ns name]} f done]
|
||||
(let [state (f)]
|
||||
(let [state (trampoline f)]
|
||||
(swap! done conj (ns-resolve ns name))
|
||||
state))
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
(start-server :bind host :port port))
|
||||
|
||||
;; nREPL is just another simple state
|
||||
(defstate nrepl :start (start-nrepl (:nrepl app-config))
|
||||
:stop (stop-server nrepl))
|
||||
(defstate nrepl :start #(start-nrepl (:nrepl app-config))
|
||||
:stop #(stop-server nrepl))
|
||||
|
||||
;; datomic schema
|
||||
(defn create-schema [conn]
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@
|
|||
edn/read-string))
|
||||
|
||||
(defstate app-config
|
||||
:start (load-config "test/resources/config.edn"))
|
||||
:start #(load-config "test/resources/config.edn"))
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@
|
|||
(.release conn) ;; usually it's not released, here just to illustrate the access to connection on (stop)
|
||||
(d/delete-database uri)))
|
||||
|
||||
(defstate conn :start (new-connection app-config)
|
||||
:stop (disconnect app-config conn))
|
||||
(defstate conn :start #(new-connection app-config)
|
||||
:stop #(disconnect app-config conn))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
[app.nyse :refer [conn]]
|
||||
[clojure.test :refer :all]))
|
||||
|
||||
(defstate should-not-start :start (constantly 42))
|
||||
(defstate should-not-start :start #(constantly 42))
|
||||
|
||||
(defn with-parts [f]
|
||||
(m/start #'app.config/app-config #'app.nyse/conn)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
[app :refer [nrepl]]
|
||||
[clojure.test :refer :all]))
|
||||
|
||||
(defstate test-conn :start (long 42)
|
||||
:stop (constantly 0))
|
||||
(defstate test-conn :start 42
|
||||
:stop #(constantly 0))
|
||||
|
||||
(defstate test-nrepl :start (vector))
|
||||
(defstate test-nrepl :start vector)
|
||||
|
||||
(deftest start-with
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@
|
|||
(defn suspend [s] (koncat s :suspended))
|
||||
(defn resume [s] (koncat s :resumed))
|
||||
|
||||
(defstate web-server :start (start :w)
|
||||
:stop (stop :w)
|
||||
:suspend (suspend :w)
|
||||
:resume (resume :w))
|
||||
(defstate web-server :start #(start :w)
|
||||
:stop #(stop :w)
|
||||
:suspend #(suspend :w)
|
||||
:resume #(resume :w))
|
||||
|
||||
(defstate q-listener :start (start :q)
|
||||
:stop (stop :q)
|
||||
:suspend (suspend :q)
|
||||
:resume (resume :q))
|
||||
(defstate q-listener :start #(start :q)
|
||||
:stop #(stop :q)
|
||||
:suspend #(suspend :q)
|
||||
:resume #(resume :q))
|
||||
|
||||
(deftest suspendable
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue