Fork me on GitHub
#mount
<
2018-01-22
>
urzds14:01:22

I manage different sub-services inside my application using mount, and I want to restart them easily. However, I do not want to restart the nREPL sub-service, since I am connected to the service using that one.

urzds14:01:48

What is the recommended way to exclude that? I tried

(defn stop []
  (mount/stop-except #'bwvisu-web.core/nrepl-server))

(defn go
  "starts all states defined by defstate"
  []
  (start)
  :ready)

(defn reset
  "stops all states defined by defstate, reloads modified source files, and restarts the states"
  []
  (stop)
  (tn/refresh :after 'dev/go))
As explained in the readme, but mount still tries to restart the nrepl-server.

arnout14:01:52

Are you calling the correct stop in reset?

urzds14:01:55

Another glitch, though probably unrelated, is that my tests (from the tests/ directory) are also being reloaded and "started" (even though there are no mount states there)...

urzds14:01:33

@arnout I litterally copy&pasted the above from my code. The complete file is this:

(ns dev
  (:require [mount.core :as mount]
            [clojure.tools.namespace.repl :as tn]
            [bwvisu-web.core]))

(defn start []
  (mount/start))

(defn stop []
  (mount/stop-except #'bwvisu-web.core/nrepl-server))

(defn go
  "starts all states defined by defstate"
  []
  (start)
  :ready)

(defn reset
  "stops all states defined by defstate, reloads modified source files, and restarts the states"
  []
  (stop)
  (tn/refresh :after 'dev/go))

arnout14:01:59

Code seems good. Does it really restart the nREPL server? Or does it (try to) start a second instance?

urzds14:01:26

Hm, I don't know. How do I figure that out? I see: #error{:cause "Address already in use (Bind failed)"

arnout15:01:55

Check, it tries to start a second instance

arnout15:01:03

It did no stop the current one

urzds15:01:31

Hm, I think the mistake is much more stupid than I thought...

arnout15:01:51

Could be due to tools.namepace reloading the bwvisu-web.core namespace, reloading the nrepl-server defstate as well.

urzds15:01:01

@arnout And I would prevent that by setting :on-reload :noop?

urzds15:01:41

I am using Cursive. I run the application using "Run nREPL with Leiningen". Leiningen is configured to start the nREPL on TCP:9998. I also have the core/nrepl-server setup to run on TCP:9998. I assume that now both the nREPL started by Cursive/Leiningen and the one started by my application are trying to run on the same port...?

arnout15:01:26

Yeah, that won't work 🙂

urzds15:01:46

Is there a convenient way to fire up the application, start the core/nrepl-server and make Cursive's REPL connect to it?

arnout15:01:02

The :on-reload option might help. I'm no expert on mount (I am on mount-lite though 😉)

urzds15:01:07

btw, I also experimented with Socket REPL and Tubular, but could not get that to work at all.

urzds15:01:28

There is something even more lightweight than mount?

arnout15:01:39

About the Cursive question; I don't know, I use Emacs.

arnout15:01:08

About the lightweight mount, see for yourself, my opinion is obviously biased.

urzds15:01:23

I'll read the blogpost in a sec.

urzds16:01:03

Shouldn't mount start all states that a particular other state uses? Or will it restrict itself to the states listed in (mount/start #'my-state), ignoring all dependencies?

tolitius18:01:10

@urzds (mount/start #'my-state) will only start #'my-state. (mount/start) will start all the states in the order of their "usage"

tolitius18:01:19

in your example above, try start with "except" nrepl, otherwise you starting a new one on top of the one that is already started

tolitius18:01:38

hence "Address already in use (Bind failed)"

urzds18:01:21

Yes, we figured that one out. one nREPL server was started by Leiningen, the other by my own code. Hence the trouble.

urzds18:01:31

Different topic: Is there a recommended way to call mount/stop on exit? I tried using this method (https://stackoverflow.com/questions/11709639/how-to-catch-ctrlc-in-clojure), but for some reason my log/info messages are not printed anymore, so I don't know whether everything actually shuts down properly.

tolitius18:01:12

(.addShutdownHook (Runtime/getRuntime)
                    (Thread. (fn [] (mount/stop))))

tolitius18:01:36

in your -main

urzds18:01:24

@tolitius I tried that. Maybe there is some trouble with the logger being shut down before the rest of the system...

urzds18:01:43

I was using plain clojure.tools.logging

tolitius18:01:16

you can add println into that inner function, or you can add https://github.com/tolitius/mount-up into the mix that will help logging all the mount interactions

urzds18:01:10

I loaded io.aviso/logging, and now I get the output I expected.