[#20] lifecycle fns take fns and values

This commit is contained in:
anatoly 2015-11-27 12:48:35 -05:00
parent 9be822b2e9
commit 1c970e152a
12 changed files with 51 additions and 47 deletions

View file

@ -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 ...))
```

View file

@ -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".

View file

@ -1,3 +0,0 @@
# Introduction to statuo
TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)

View file

@ -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

View file

@ -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,

View file

@ -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))

View file

@ -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]

View file

@ -10,4 +10,4 @@
edn/read-string))
(defstate app-config
:start (load-config "test/resources/config.edn"))
:start #(load-config "test/resources/config.edn"))

View file

@ -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))

View file

@ -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)

View file

@ -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

View file

@ -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