[#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: Creating state is easy:
```clojure ```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` In case this state needs to be cleaned / destryed between reloads, there is also `:stop`
```clojure ```clojure
(defstate conn :start (create-conn) (defstate conn :start create-conn
:stop (disconnect 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 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"] #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 ### Using State
For example let's say an `app` needs a connection above. No problem: 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]])) (:require [mount.core :refer [defstate]]))
(defstate app-config (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: 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]] (:require [mount.core :refer [defstate]]
[app.config :refer [app-config]])) [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) [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: In additiong to `start` / `stop` functions, a state can also have `resume` and, if needed, `suspend` ones:
```clojure ```clojure
(defstate web-server :start (start-server ...) (defstate web-server :start #(start-server ...)
:resume (resume-server ...) :resume #(resume-server ...)
:stop (stop-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: Mount is pretty much:
```clojure ```clojure
(defstate name :start (fn) (defstate name :start fn
:stop (fn)) :stop fn)
``` ```
no "ceremony". 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` * [inside](https://github.com/tolitius/mount/blob/with-args/test/app/nyse.clj#L17) a `defstate`
```clojure ```clojure
(defstate conn :start (new-connection (mount/args)) (defstate conn :start #(new-connection (mount/args))
:stop (disconnect (mount/args) conn)) :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: * 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 ```bash
$ lein do clean, uberjar $ 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: Since we have a default for a Datomic URI, it'll work with no arguments:
```bash ```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.290 [main] INFO mount - >> starting.. app-config
22:12:03.293 [main] INFO mount - >> starting.. conn 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: Now let's ask it to help us:
```bash ```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.798 [main] INFO mount - >> starting.. app-config
22:13:48.799 [main] INFO 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.. And finally let's connect to the Single Malt Database. It's Friday..
```bash ```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.733 [main] INFO mount - >> starting.. app-config
22:16:10.737 [main] INFO mount - >> starting.. conn 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: and the reloadable state:
```clojure ```clojure
(defn start-nyse [] (defn start-nyse [{:keys [www]}]
(create-nyse-schema) ;; creating schema (usually done long before the app is started..)
(-> (routes mount-example-routes) (-> (routes mount-example-routes)
(handler/site) (handler/site)
(run-jetty {:join? false (run-jetty {:join? false
:port (get-in app-config [:www :port])}))) :port (:port www)})))
(defstate nyse-app :start (start-nyse) (defstate nyse-app :start #(start-nyse app-config)
:stop (.stop nyse-app)) ;; it's a "org.eclipse.jetty.server.Server" at this point :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, 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) (validate lifecycle)
(let [s-meta (cond-> {:mount-state mount-state (let [s-meta (cond-> {:mount-state mount-state
:order (make-state-seq state) :order (make-state-seq state)
:start `(fn [] (~@start)) :start `(fn [] ~start)
:started? false} :started? false}
stop (assoc :stop `(fn [] (~@stop))) stop (assoc :stop `(fn [] ~stop))
suspend (assoc :suspend `(fn [] (~@suspend))) suspend (assoc :suspend `(fn [] ~suspend))
resume (assoc :resume `(fn [] (~@resume))))] resume (assoc :resume `(fn [] ~resume)))]
`(defonce ~(with-meta state (merge (meta state) s-meta)) `(defonce ~(with-meta state (merge (meta state) s-meta))
(NotStartedState. ~(str state)))))) (NotStartedState. ~(str state))))))
(defn- record! [{:keys [ns name]} f done] (defn- record! [{:keys [ns name]} f done]
(let [state (f)] (let [state (trampoline f)]
(swap! done conj (ns-resolve ns name)) (swap! done conj (ns-resolve ns name))
state)) state))

View file

@ -11,8 +11,8 @@
(start-server :bind host :port port)) (start-server :bind host :port port))
;; nREPL is just another simple state ;; nREPL is just another simple state
(defstate nrepl :start (start-nrepl (:nrepl app-config)) (defstate nrepl :start #(start-nrepl (:nrepl app-config))
:stop (stop-server nrepl)) :stop #(stop-server nrepl))
;; datomic schema ;; datomic schema
(defn create-schema [conn] (defn create-schema [conn]

View file

@ -10,4 +10,4 @@
edn/read-string)) edn/read-string))
(defstate app-config (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) (.release conn) ;; usually it's not released, here just to illustrate the access to connection on (stop)
(d/delete-database uri))) (d/delete-database uri)))
(defstate conn :start (new-connection app-config) (defstate conn :start #(new-connection app-config)
:stop (disconnect app-config conn)) :stop #(disconnect app-config conn))

View file

@ -3,7 +3,7 @@
[app.nyse :refer [conn]] [app.nyse :refer [conn]]
[clojure.test :refer :all])) [clojure.test :refer :all]))
(defstate should-not-start :start (constantly 42)) (defstate should-not-start :start #(constantly 42))
(defn with-parts [f] (defn with-parts [f]
(m/start #'app.config/app-config #'app.nyse/conn) (m/start #'app.config/app-config #'app.nyse/conn)

View file

@ -5,10 +5,10 @@
[app :refer [nrepl]] [app :refer [nrepl]]
[clojure.test :refer :all])) [clojure.test :refer :all]))
(defstate test-conn :start (long 42) (defstate test-conn :start 42
:stop (constantly 0)) :stop #(constantly 0))
(defstate test-nrepl :start (vector)) (defstate test-nrepl :start vector)
(deftest start-with (deftest start-with

View file

@ -15,15 +15,15 @@
(defn suspend [s] (koncat s :suspended)) (defn suspend [s] (koncat s :suspended))
(defn resume [s] (koncat s :resumed)) (defn resume [s] (koncat s :resumed))
(defstate web-server :start (start :w) (defstate web-server :start #(start :w)
:stop (stop :w) :stop #(stop :w)
:suspend (suspend :w) :suspend #(suspend :w)
:resume (resume :w)) :resume #(resume :w))
(defstate q-listener :start (start :q) (defstate q-listener :start #(start :q)
:stop (stop :q) :stop #(stop :q)
:suspend (suspend :q) :suspend #(suspend :q)
:resume (resume :q)) :resume #(resume :q))
(deftest suspendable (deftest suspendable