Open sdave2 opened 7 years ago
To summarize the discussion with @tolitius:
mount/reset
makes sense as a dev-time tool. The reset
would stop all started states unconditionally and clear the internal Mount state.The only open question is how to deal with states which fail to stop cleanly:
stop
which stops the STOP operation on the first exceptionreset
to return a set of Vars which failed to stop cleanly so that e.g. the dangling connection can still be forced closedAfter thinking a bit more a separate API such as reset
is unnecessary, a call to (mount/stop)
should handle this use case.
Pushed changes to 0.1.12-SNAPSHOT
. A call to (mount/stop)
on failure to stop a state will report it and mark the state as :stopped
. This would allow to:
(mount/stop)
will return all states that were successfully stopped.
boot.user=> (defstate a :start 42 :stop (throw (RuntimeException. "BOOM")))
#'boot.user/a
boot.user=> (defstate b :start 1 :stop 2)
#'boot.user/b
boot.user=> (mount/start)
{:started ["#'boot.user/a" "#'boot.user/b"]}
boot.user=> a
42
boot.user=> b
1
boot.user=> (mount/stop)
#error {
:cause "BOOM"
:via
[{:type clojure.lang.ExceptionInfo
:message "could not stop [#'boot.user/a] due to"
...}]}
{:stopped ["#'boot.user/b"]}
Since a
state could not be stopped, it still points to its original value after the "stop" function was called:
boot.user=> a
42
boot.user=> b
#object[mount.core.NotStartedState 0x2156abe2 "'#'boot.user/b' is not started (to start all the states call mount/start)"]
However from mount's perspective a
is :stopped
and can be started / redefined again. This allows a manual "force stop" of a
in REPL.
We can now redefine a
's stop function to "fix" the exception:
boot.user=> (defstate a :start 42 :stop 34)
#'boot.user/a
boot.user=> (mount/start)
{:started ["#'boot.user/a" "#'boot.user/b"]}
boot.user=> a
42
boot.user=> b
1
boot.user=> (mount/stop)
{:stopped ["#'boot.user/b" "#'boot.user/a"]}
boot.user=> a
#object[mount.core.NotStartedState 0xa04c91c "'#'boot.user/a' is not started (to start all the states call mount/start)"]
boot.user=> b
#object[mount.core.NotStartedState 0x56b0c866 "'#'boot.user/b' is not started (to start all the states call mount/start)"]
Situation I ran into:
This is interesting. I defined a var with a
defstate
but made a mistake the first time around.;; not the same mistake but it will help elaborate what I’m trying to explain
(mount/start) ;; this works fine. (mount/stop) ;; produces the error.
ClassCastException clojure.lang.Keyword cannot be cast to clojure.lang.IAtom clojure.core/reset! (core.clj:2273)
;; trying to re-define
conn
but keep running into the same error.A function to reset all the states/connections even if they produce error would be nice. This was mentioned on Slack's mount channel by @tolitius . "it might make sense to potentially have a some kind of
(mount/reset)
that could take params: i.e.(mount/reset :ignore-errors true)
. which, if well documented, could help in situations like this one."