Fork me on GitHub
#mount
<
2017-07-08
>
onetom20:07:47

@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

onetom20:07:01

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

onetom20:07:28

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

onetom20:07:07

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

onetom20:07:47

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

onetom20:07:06

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

onetom20:07:08

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

onetom20:07:39

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

onetom21:07:04

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

onetom21:07:50

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]

tolitius21:07:47

@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 🙂

onetom21:07:39

sounds dangerous too! but thanks anyway

onetom21:07:40

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

onetom21:07:37

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

onetom21:07:15

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 - 

boot.user=> (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=> Bye for now!

onetom21:07:17

@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 (-> (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

onetom21:07:34

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 "<how can i get the conn???>")))
https://gitlab.com/onetom/mount-lite-example/blob/master/src/app/db.clj#L35-37

onetom22:07:04

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

(defn with-test-db [tests]
  (-> (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

onetom22:07:47

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...