start and stop order are... [in]

This commit is contained in:
anatoly 2015-10-20 15:41:53 -04:00
parent 8b0744cd63
commit 26322005e6
2 changed files with 34 additions and 12 deletions

View file

@ -104,6 +104,17 @@ this `app-config`, being top level, can be used in other namespaces, including t
[here](https://github.com/tolitius/mount/blob/master/test/app/nyse.clj) [here](https://github.com/tolitius/mount/blob/master/test/app/nyse.clj)
is an example of a Datomic connection that "depends" on a similar `app-config`. is an example of a Datomic connection that "depends" on a similar `app-config`.
## Start and Stop Order
Since dependencies are "injected" by `require`ing on the namespace level, `mount` trusts Clojure compiler to
maintain the start order for all the `defstates`.
The "start" order is then recorded and replayed on each `(reset)`.
The "stop" order is simply `(reverse "start order")`.
You can see examples of start and stop flows in the [example app](https://github.com/tolitius/mount#mount-and-develop).
## The Importance of Being Reloadable ## The Importance of Being Reloadable
`mount` has start and stop functions that will walk all the states created with `defstate` and start / stop them `mount` has start and stop functions that will walk all the states created with `defstate` and start / stop them
@ -129,8 +140,11 @@ To try it out, clone `mount`, get to REPL and switch to `(dev)`:
$ lein repl $ lein repl
user=> (dev) user=> (dev)
20:37:29.461 [nREPL-worker-0] INFO mount.config - loading config from test/resources/config.edn 15:30:32.412 [nREPL-worker-1] DEBUG mount - >> starting.. app-config
20:37:29.477 [nREPL-worker-0] INFO mount.nyse - creating a connection to datomic: datomic:mem://mount 15:30:32.414 [nREPL-worker-1] INFO app.config - loading config from test/resources/config.edn
15:30:32.422 [nREPL-worker-1] DEBUG mount - >> starting.. conn
15:30:32.430 [nREPL-worker-1] INFO app.nyse - conf: {:datomic {:uri datomic:mem://mount}, :h2 {:classname org.h2.Driver, :subprotocol h2, :subname jdbc:h2:mem:mount, :user sa, :password }, :rabbit {:api-port 15672, :password guest, :queue r-queue, :username guest, :port 5672, :node jabit, :exchange-type direct, :host 192.168.1.1, :vhost /captoman, :auto-delete-q? true, :routing-key , :exchange foo}}
15:30:32.430 [nREPL-worker-1] INFO app.nyse - creating a connection to datomic: datomic:mem://mount
dev=> dev=>
``` ```
@ -150,11 +164,16 @@ once something is changed in the code, or you just need to reload everything, do
```clojure ```clojure
dev=> (reset) dev=> (reset)
20:38:43.244 [nREPL-worker-1] INFO mount.nyse - disconnecting from datomic:mem://mount 15:32:44.343 [nREPL-worker-2] DEBUG mount - << stopping.. conn
:reloading (mount mount.config mount.nyse mount.utils.datomic mount.app dev) 15:32:44.343 [nREPL-worker-2] INFO app.nyse - disconnecting from datomic:mem://mount
15:32:44.344 [nREPL-worker-2] DEBUG mount - << stopping.. app-config
20:38:43.287 [nREPL-worker-1] INFO mount.config - loading config from test/resources/config.edn :reloading (app.config app.nyse app.utils.datomic app dev)
20:38:43.296 [nREPL-worker-1] INFO mount.nyse - creating a connection to datomic: datomic:mem://mount 15:32:44.371 [nREPL-worker-2] DEBUG mount - >> starting.. app-config
15:32:44.372 [nREPL-worker-2] INFO app.config - loading config from test/resources/config.edn
15:32:44.380 [nREPL-worker-2] DEBUG mount - >> starting.. conn
15:32:44.382 [nREPL-worker-2] INFO app.nyse - conf: {:datomic {:uri datomic:mem://mount}, :h2 {:classname org.h2.Driver, :subprotocol h2, :subname jdbc:h2:mem:mount, :user sa, :password }, :rabbit {:api-port 15672, :password guest, :queue r-queue, :username guest, :port 5672, :node jabit, :exchange-type direct, :host 192.168.1.1, :vhost /captoman, :auto-delete-q? true, :routing-key , :exchange foo}}
15:32:44.382 [nREPL-worker-2] INFO app.nyse - creating a connection to datomic: datomic:mem://mount
:ready :ready
``` ```

View file

@ -1,7 +1,7 @@
(ns mount (ns mount
(:require [clojure.tools.macro :as macro] (:require [clojure.tools.macro :as macro]
[clojure.tools.namespace.repl :refer [disable-reload!]] [clojure.tools.namespace.repl :refer [disable-reload!]]
[clojure.tools.logging :refer [info]])) [clojure.tools.logging :refer [info debug]]))
(disable-reload!) (disable-reload!)
@ -22,7 +22,7 @@
{:start start :stop stop}) {:start start :stop stop})
(defmacro defstate [state & body] (defmacro defstate [state & body]
(info "calling defstate: " state ", body: " body) (debug ">> starting.. " state)
(let [[state [c cf d df]] (macro/name-with-attributes state body) (let [[state [c cf d df]] (macro/name-with-attributes state body)
{:keys [start stop]} (validate {c cf d df})] {:keys [start stop]} (validate {c cf d df})]
(let [s-meta (-> {:session-id session-id (let [s-meta (-> {:session-id session-id
@ -35,25 +35,28 @@
(defn- up [var {:keys [ns name start started?]}] (defn- up [var {:keys [ns name start started?]}]
(when-not started? (when-not started?
(debug ">> starting.. " name)
(intern ns (symbol name) (start)) (intern ns (symbol name) (start))
(alter-meta! var assoc :started? true))) (alter-meta! var assoc :started? true)))
(defn- down [var {:keys [stop started?]}] (defn- down [var {:keys [name stop started?]}]
(when started? (when started?
(debug "<< stopping.. " name)
(alter-meta! var assoc :started? false) (alter-meta! var assoc :started? false)
(when stop (stop)))) (when stop (stop))))
(defn- f-states [f] (defn- f-states [f order]
(->> (all-ns) (->> (all-ns)
(mapcat ns-interns) (mapcat ns-interns)
(map second) (map second)
(filter #(= (:session-id (meta %)) session-id)) (filter #(= (:session-id (meta %)) session-id))
(sort-by (comp :order meta) order)
(map #(f % (meta %))))) (map #(f % (meta %)))))
(defn start [] (defn start []
(doall (doall
(f-states up))) (f-states up <)))
(defn stop [] (defn stop []
(doall (doall
(f-states down))) (f-states down >)))