tolitius/mount

remove tools.logging dependency

tolitius opened this issue · 1 comments

Logging Choice

There are logging alternatives such as unilog or timbre, and mount should not bring tools.logging with it: while it can be excluded, it's just an extra step that should be avoided.

Visual Help

The way mount currently logging states while bringing them up and down is quite helpful to resolve any exceptions during start/stop/suspend/resume, since it is visible which state caused it:

22:13:06.591 [nREPL-worker-0] INFO  mount.core - >> starting..  app-config
22:13:06.592 [nREPL-worker-0] INFO  mount.core - >> starting..  conn
22:13:06.767 [nREPL-worker-0] INFO  mount.core - >> starting..  web-server

BindException Address already in use  java.net.PlainSocketImpl.socketBind (PlainSocketImpl.java:-2)

so it is obvious that the answer to the problem is in starting.. web-server.

Exception Details

On the other hand, mount adds details to the exception to make is clear when/where it occurred. For example if the above exception is looked at in REPL *e, it would have the details about web-server:

#error {
 :cause "Address already in use"
 :via
 [{:type java.lang.RuntimeException
   :message "could not start [web-server] due to"                 <<<<<<<<<<<<<<
   :at [mount.core$up$fn__4959 invoke "core.clj" 55]}
  {:type java.net.BindException
   :message "Address already in use"
   :at [java.net.PlainSocketImpl socketBind "PlainSocketImpl.java" -2]}]
 :trace
 [[java.net.PlainSocketImpl socketBind "PlainSocketImpl.java" -2]
  [java.net.AbstractPlainSocketImpl bind "AbstractPlainSocketImpl.java" 382]

Therefore I believe it is safe to remove mount logging all together.

Needs Thinking

If logging is removed, and there are no exceptions during start/stop, it is not obvious which states have started / stopped / suspended / resumed.

Feels like all lifecycle functions need to simply either return all the states that they changed OR return the current app status:

({:name conn, :started? true, :suspended? false}
 {:name nrepl, :started? true, :suspended? false}
 {:name q-listener, :started? true}
 {:name web-server, :started? false}
 {:name test-conn, :started? false}
 {:name test-nrepl, :started? false}
 {:name app-config, :started? true, :suspended? false})

With simply returning a set of states a particular lifecycle method affected, there is a caveat: start can also resume.

mount now returns all the states that were changed by start/stop/suspend/resume:

dev=> (mount/start)
{:started [#'app.config/app-config 
           #'app.nyse/conn 
           #'app/nrepl
           #'check.suspend-resume-test/web-server
           #'check.suspend-resume-test/q-listener]}
dev=> (mount/suspend)
{:suspended [#'check.suspend-resume-test/web-server
             #'check.suspend-resume-test/q-listener]}
dev=> (mount/start)
{:started [#'check.suspend-resume-test/web-server
           #'check.suspend-resume-test/q-listener]}

the interesting bit here is vector vs. set: all the states are returned in order they were changed