From d8749261dfb50940db5a8362b097a009b084a278 Mon Sep 17 00:00:00 2001 From: anatoly Date: Sun, 31 Jan 2016 14:08:49 -0500 Subject: [PATCH] #36: adding ^{:on-reload action} actions are: :noop :stop :restart :restart is a default action: i.e. if no :on-reload meta is added --- src/mount/core.cljc | 11 +++-- test/core/mount/test/helper.cljc | 8 ++++ test/core/mount/test/on_reload.cljc | 54 ++++++++++++++++++++++ test/core/mount/test/on_reload_helper.cljc | 21 +++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test/core/mount/test/on_reload.cljc create mode 100644 test/core/mount/test/on_reload_helper.cljc diff --git a/src/mount/core.cljc b/src/mount/core.cljc index 41e0152..b1036d5 100644 --- a/src/mount/core.cljc +++ b/src/mount/core.cljc @@ -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) diff --git a/test/core/mount/test/helper.cljc b/test/core/mount/test/helper.cljc index e02bf32..e020c5c 100644 --- a/test/core/mount/test/helper.cljc +++ b/test/core/mount/test/helper.cljc @@ -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) diff --git a/test/core/mount/test/on_reload.cljc b/test/core/mount/test/on_reload.cljc new file mode 100644 index 0000000..5fc6ddd --- /dev/null +++ b/test/core/mount/test/on_reload.cljc @@ -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)))))) diff --git a/test/core/mount/test/on_reload_helper.cljc b/test/core/mount/test/on_reload_helper.cljc new file mode 100644 index 0000000..d49a428 --- /dev/null +++ b/test/core/mount/test/on_reload_helper.cljc @@ -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)) +