mount

urzds 2018-01-22T14:46:09.000254Z

Hi!

urzds 2018-01-22T14:47:22.000810Z

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.

urzds 2018-01-22T14:49:48.000434Z

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.

arnout 2018-01-22T14:52:52.000425Z

Are you calling the correct stop in reset?

urzds 2018-01-22T14:53:55.000128Z

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

urzds 2018-01-22T14:55:33.000866Z

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

arnout 2018-01-22T14:56:59.000424Z

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

urzds 2018-01-22T14:59:26.000621Z

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

arnout 2018-01-22T15:00:55.000039Z

Check, it tries to start a second instance

arnout 2018-01-22T15:01:03.000618Z

It did no stop the current one

urzds 2018-01-22T15:01:31.000988Z

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

arnout 2018-01-22T15:01:51.000306Z

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

urzds 2018-01-22T15:03:01.000627Z

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

urzds 2018-01-22T15:04:41.000323Z

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

arnout 2018-01-22T15:05:26.000235Z

Yeah, that won't work 🙂

urzds 2018-01-22T15:05:46.000767Z

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

arnout 2018-01-22T15:06:02.000457Z

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

urzds 2018-01-22T15:06:07.000408Z

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

urzds 2018-01-22T15:06:28.000280Z

There is something even more lightweight than mount?

arnout 2018-01-22T15:07:39.000636Z

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

arnout 2018-01-22T15:08:08.000438Z

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

urzds 2018-01-22T15:10:23.000999Z

I'll read the blogpost in a sec.

urzds 2018-01-22T16:14:03.000667Z

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?

tolitius 2018-01-22T18:05:10.000212Z

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

urzds 2018-01-22T18:06:15.000025Z

@tolitius Thanks.

tolitius 2018-01-22T18:07:19.000583Z

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

tolitius 2018-01-22T18:07:38.000062Z

hence "Address already in use (Bind failed)"

urzds 2018-01-22T18:08:21.000013Z

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

urzds 2018-01-22T18:08:31.000551Z

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.

tolitius 2018-01-22T18:09:12.000173Z

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

tolitius 2018-01-22T18:09:36.000368Z

in your -main

urzds 2018-01-22T18:13:24.000464Z

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

urzds 2018-01-22T18:13:43.000699Z

I was using plain clojure.tools.logging

tolitius 2018-01-22T18:20:16.000896Z

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

urzds 2018-01-22T18:23:10.000879Z

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

tolitius 2018-01-22T18:24:39.000505Z

great