mount

onetom 2017-07-08T20:23:47.607424Z

@tolitius i've modernized the dependencies in yurt (https://github.com/tolitius/yurt/pull/5) but when i do a (mount/start) (mount/stop) (mount/start) i get Address already in use

onetom 2017-07-08T20:25:01.613015Z

since i couldn't run the original version i can't easily compare if it's an issue which was already present there or not

onetom 2017-07-08T20:28:28.628517Z

also if i do a (mount/start) (reset) which in turn triggers this address-already-in-use error, then my dev namespace is blown away:

java.lang.RuntimeException: Unable to resolve symbol: reset in this context

onetom 2017-07-08T20:32:07.645712Z

i understand (reset) is trying to reload the dev ns too, since it requires the neo.* namespaces which i have modified, but the error is not happening while loading that namespace but when (tn/refresh) is trying to do a (mount/start) again

onetom 2017-07-08T20:32:47.648581Z

i tried to protect the dev ns by putting a (tn/disable-reload!) at the beginning of it but that didn't help

onetom 2017-07-08T20:55:06.745774Z

im trying to debug the situation but i can't seem to be able to print anything from a stop handler:

dev=> (mount/defstate s2 :start 2 :stop #(info "Stopping state" %)) (mount/start #'s2) (mount/stop #'s2) (resolve 'info)
#'dev/s2
INFO  utils.logging - >> starting.. #'dev/s2
{:started ["#'dev/s2"]}
INFO  utils.logging - << stopping.. #'dev/s2
{:stopped ["#'dev/s2"]}
#'clojure.tools.logging/info

onetom 2017-07-08T20:59:08.762076Z

it tried with println, prn, boot.util/info, throw but nothing worked. im not even sure if it's actually calling the stop function... i will try with an atom

onetom 2017-07-08T20:59:39.764110Z

dev=> (def x (atom 0)) (mount/defstate s1 :start 1 :stop #(swap! x + %)) (mount/start #'s1) (mount/stop #'s1) @x
#'dev/x
#'dev/s1
INFO  utils.logging - >> starting.. #'dev/s1
{:started ["#'dev/s1"]}
INFO  utils.logging - << stopping.. #'dev/s1
{:stopped ["#'dev/s1"]}
0

onetom 2017-07-08T21:00:04.766172Z

now it really seems that the stop function is actually not called =:-/

onetom 2017-07-08T21:04:50.787654Z

oh, if i use yurt, then the stop function seems to be called:

dev=> (def x (atom 0))
           (let [bp (yurt/blueprint)
                  y (yurt/build bp {:only ["dev/s1"]})]
              [(:components y) (yurt/destroy y) @x])
#'dev/x
INFO  utils.logging - >> starting.. #'dev/s1
[{"dev/s1" 1} {:stopped #{"dev/s1"}} 1]

tolitius 2017-07-08T21:14:47.829532Z

@onetom driving 🙂, but this should work (with just mount):

(def x (atom 0)) (mount/defstate s1 :start 1 :stop (swap! x + s1)) (mount/start #'s1) (mount/stop #'s1) @x
i.e. :stop #(swap! x + %) => :stop (swap! x + s1) #() does not really get called on :stop. a (swap! x + s1) would be. the idea behind including #() is to make a state to be a function:
(defstate fun :start #(inc 41))
=> (mount/start #'fun)
=> (#'fun)
42
takes time to type with one hand on a wheel 🙂

onetom 2017-07-08T21:19:39.850778Z

sounds dangerous too! but thanks anyway

onetom 2017-07-08T21:20:40.855568Z

however for stopping a jetty server the yurt neo app has this example:

(defstate neo-app :start (start-neo db config)
                  :stop #(.stop %))  ;; it's a "org.eclipse.jetty.server.Server" at this point

onetom 2017-07-08T21:21:37.859522Z

which i would think is logical to support, not only in case of yurt but also in case of anonymous states which are just whipped up for the sake of substitution in tests for example

onetom 2017-07-08T21:24:15.871162Z

this worked indeed:

λ echo '(require \'[mount.core :as mount]) (def x (atom 0)) (mount/defstate s1 :start 1 :stop (swap! x + s1)) (mount/start #\'s1) (mount/stop #\'s1) @x' | boot -BP -d mount:0.1.11 repl -I

nREPL server started on port 61752 on host 127.0.0.1 - <nrepl://127.0.0.1:61752>

boot.user=&gt; (require '[mount.core :as mount]) (def x (atom 0)) (mount/defstate s1 :start 1 :stop (swap! x + s1)) (mount/start #'s1) (mount/stop #'s1) @x
nil
#'boot.user/x
#'boot.user/s1
{:started ["#'boot.user/s1"]}
{:stopped ["#'boot.user/s1"]}
1
boot.user=&gt; Bye for now!

onetom 2017-07-08T21:45:17.957973Z

@arnout i tried to see how an actual test would look like using your with-session feature. here is a working version where the system under test runs in its own little "session thread" and completes, because if i put the clojure.test/is inside it, then clojure.test gets confused quite understandably:

(deftest test-conn-test
    (let [res (-&gt; (mount/with-session
                    (mount/with-substitutes
                      [#'conn (test-conn)]
                      (mount/start))
                    (tx! [{:db/id "e" :str "asd"}])
                    (q '[:find (pull ?e [:str]) .
                         :where [?e :str "asd"]]))
                  :result deref)]
      (is (= {:str "asd"} res))))
— https://gitlab.com/onetom/mount-lite-example/blob/master/test/app/db_test.clj#L8-15

onetom 2017-07-08T21:48:34.970178Z

however the bigger problem is the same as above; how can i clean up my datomic connection if i use an anonymous state? my state i substitute the real one looks like this:

(defn test-conn []
  (mount/state :start (connect-in-memory-db test-uri)
               :stop (cleanup-in-memory-db test-uri "&lt;how can i get the conn???&gt;")))
— https://gitlab.com/onetom/mount-lite-example/blob/master/src/app/db.clj#L35-37

onetom 2017-07-08T22:05:04.035308Z

however, this is how i would like to see it work:

(defn with-test-db [tests]
  (-&gt; (mount/with-session
        (mount/with-substitutes
          [#'conn (test-conn)]
          (mount/start))
        (tests))
      :result deref))

(use-fixtures :each with-test-db)

(deftest test-inside-session-using-fixtures
  (tx! [{:db/id "e" :str "asd"}])
  (is (= {:str "asd"}
         (q '[:find (pull ?e [:str]) .
              :where [?e :str "asd"]]))))
— https://gitlab.com/onetom/mount-lite-example/blob/master/test/app/pretty_db_test.clj#L7-21

onetom 2017-07-08T22:07:47.045748Z

bit this one fails because the is assertion runs on a different thread as the clojure.test/run-tests and im getting incorrect test summaries at the end OR it returns the guts of the Cursive test integration if I run it with Cursive...