Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A reset function which will reset all the states even if there are errors. #63

Open
sdave2 opened this issue Sep 22, 2016 · 2 comments
Open

Comments

@sdave2
Copy link

sdave2 commented Sep 22, 2016

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

(def conn1-atom (atom nil))
(defstate conn
  :start (reset! conn1-atom :started)
  :stop (reset! :started conn1-atom))  ;; there is a mistake in :stop.

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

(defstate conn
  :start (reset! conn1-atom :started)
  :stop (reset! conn1-atom :stopped))

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

@dm3
Copy link
Contributor

dm3 commented Mar 9, 2017

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:

  • we don't want to change the semantics of stop which stops the STOP operation on the first exception
  • one option is for reset to return a set of Vars which failed to stop cleanly so that e.g. the dangling connection can still be forced closed

@tolitius
Copy link
Owner

After 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:

  • stop all the subsequent states
  • manually handle states that could not stop in REPL
  • redefine states "stop" functions in the same REPL session if needed

(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)"]

tolitius added a commit that referenced this issue Mar 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants