#36: adding ^{:on-reload action}

actions are: :noop :stop :restart

:restart is a default action: i.e. if no :on-reload meta is added
This commit is contained in:
anatoly 2016-01-31 14:08:49 -05:00
parent 92736ba2d0
commit d8749261df
4 changed files with 91 additions and 3 deletions

View file

@ -131,15 +131,20 @@
(up name state (atom #{})))
@inst)))
(defn on-reload-meta [s-var]
(or (-> s-var meta :on-reload)
:restart)) ;; restart by default on ns reload
;;TODO: make private after figuring out the inconsistency betwen cljs compile stages
;; (i.e. _sometimes_ this, if private, is not seen by expanded "defmacro" on cljs side)
(defn mount-it [s-var s-name s-meta]
(let [with-inst (assoc s-meta :inst (atom (NotStartedState. s-name))
:var s-var)
existing? (cleanup-if-dirty s-name "(namespace was recompiled)")]
on-reload (on-reload-meta s-var)
existing? (when-not (= :noop on-reload)
(cleanup-if-dirty s-name "(namespace was recompiled)"))]
(update-meta! [s-name] with-inst)
(when existing?
(when (and existing? (= :restart on-reload))
(log (str ">> starting.. " s-name " (namespace was recompiled)"))
(up s-name with-inst (atom #{})))))
@ -155,7 +160,7 @@
:status #{:stopped}}
stop (assoc :stop `(fn [] ~stop))
suspend (assoc :suspend `(fn [] ~suspend))
resume (assoc :resume `(fn [] ~resume)))]
resume (assoc :resume `(fn [] ~resume)))]
`(do
(~'defonce ~state (DerefableState. ~state-name))
(mount-it (~'var ~state) ~state-name ~s-meta)

View file

@ -18,3 +18,11 @@
(defstate helper :start :started
:stop (reset! forty-two :cleaned))
(def counter (atom {:a {:started 0 :stopped 0}
:b {:started 0 :stopped 0}
:c {:started 0 :stopped 0}}))
(defn inc-counter [state status]
(swap! counter update-in [state status] inc)
status)

View file

@ -0,0 +1,54 @@
(ns mount.test.on-reload
(:require
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
[mount.core :as mount :refer-macros [defstate]]
[tapp.websockets :refer [system-a]]
[tapp.conf :refer [config]]
[tapp.audit-log :refer [log]]]
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
[mount.core :as mount :refer [defstate]]
[tapp.example]])
[mount.test.helper :refer [dval helper forty-two counter inc-counter]]
[mount.test.on-reload-helper :refer [a b c]]))
#?(:clj (alter-meta! *ns* assoc ::load false))
#?(:clj
(defn abc [f]
(mount/start #'mount.test.on-reload-helper/a
#'mount.test.on-reload-helper/b
#'mount.test.on-reload-helper/c)
(f)
(mount/stop)))
(use-fixtures :each
#?(:cljs {:before #(mount/start #'mount.test.on-reload-helper/a
#'mount.test.on-reload-helper/b
#'mount.test.on-reload-helper/c)
:after mount/stop}
:clj abc))
#?(:clj
(deftest restart-by-default
(is (= '(:started) (distinct (map dval [a b c]))))
(let [pre-reload @counter]
(require 'mount.test.on-reload-helper :reload)
;; "a" is marked as :noop on reload
(is (instance? mount.core.NotStartedState (dval a))) ;; (!) stale reference of old a is still there somewhere
(is (= (-> pre-reload :a)
(-> @counter :a)))
;; "b" is marked as :stop on reload
(is (instance? mount.core.NotStartedState (dval b)))
(is (= (-> pre-reload :b :started)
(-> @counter :b :started)))
(is (= (inc (-> pre-reload :b :stopped))
(-> @counter :b :stopped)))
;; "c" is not marked on reload, using "restart" as default
(is (= :started (dval c)))
(is (= (inc (-> pre-reload :c :started))
(-> @counter :c :started)))
(is (= (inc (-> pre-reload :c :stopped))
(-> @counter :c :stopped))))))

View file

@ -0,0 +1,21 @@
(ns mount.test.on-reload-helper
(:require
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
[mount.core :as mount :refer-macros [defstate]]
[tapp.websockets :refer [system-a]]
[tapp.conf :refer [config]]
[tapp.audit-log :refer [log]]]
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
[mount.core :as mount :refer [defstate]]
[tapp.example]])
[mount.test.helper :refer [inc-counter]]))
(defstate ^{:on-reload :noop} a :start (inc-counter :a :started)
:stop (inc-counter :a :stopped))
(defstate ^{:on-reload :stop} b :start (inc-counter :b :started)
:stop (inc-counter :b :stopped))
(defstate c :start (inc-counter :c :started)
:stop (inc-counter :c :stopped))