@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
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
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
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
i tried to protect the dev
ns by putting a (tn/disable-reload!)
at the beginning of it but that didn't help
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
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
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
now it really seems that the stop function is actually not called =:-/
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]
@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 🙂sounds dangerous too! but thanks anyway
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
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
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=> (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!
@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-15however 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-37however, 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-21bit 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...