component

vinai 2017-09-05T08:11:39.000242Z

I'm currently learning to work with component, please excuse me if this is a n00b question. Calling reloaded.repl/start, stop, reset, reset-all, go, suspend and resume on the repl in the user namespace works. However, if I hit C-c C-x (that is cider-refresh) I don't get an error message, but jetty isn't reachable afterwards, even though the port is still blocked. Calling (stop) and (start) afterwards manually doesn't seem to affect any components any more. Here is the *Messages* output for the command:

cider-refresh: Calling reloaded.repl/suspend

cider-refresh: Successfully called reloaded.repl/suspend

cider-refresh: Reloading (re-frame.db re-frame.loggers re-frame.registrar re-frame.interceptor re-frame.cofx re-frame.utils re-frame.trace re-frame.subs re-frame.std-interceptors re-frame.events re-frame.router re-frame.fx re-frame.core com.stuartsierra.dependency example.config com.stuartsierra.component example.routes example.application example.example-test example.common user example.common-test)

cider-refresh: Reloading successful

cider-refresh: Calling reloaded.repl/resume

cider-refresh: Successfully called reloaded.repl/resume
The only way I have managed to get back into a working state is by restarting the JVM. How can I debug what is going wrong?

vinai 2017-09-05T08:25:15.000082Z

Following the steps that reset does manually also works:

(reloaded.repl/suspend)
(clojure.tools.namespace.repl/refresh :after `reloaded.repl/resume)

vinai 2017-09-05T08:25:42.000250Z

What am I missing here?

2017-09-05T17:29:50.000476Z

@vinai likely refresh is destroying the var that contained the server, the only safe option is to make sure you stop the component before reloading the code

2017-09-05T17:30:23.000571Z

I don’t know cider very well, but I’d imagine it provides some customization for hooks to call before reloading?

vinai 2017-09-05T17:31:21.000106Z

Thanks for responding @noisesmith. The customization hook runs reloaded.repl/suspend before and reloaded.repl/resume afterwards.

2017-09-05T17:32:20.000497Z

wouldn’t you want to use stop and start instead?

2017-09-05T17:33:09.000121Z

if you put the component in a top level binding, refresh (or even reload if you don’t use defonce) will destroy the accessible binding and you won’t be able to access it to stop it after that point

2017-09-05T17:33:20.000022Z

so the only safe thing is to destroy it before reloading code

vinai 2017-09-05T17:33:58.000564Z

suspend and resume seems to do the same as stop and start for most components. If I call it manually suspend calls .stop on the jetty instance var.

vinai 2017-09-05T17:34:53.000332Z

I don't know elisp but from what I can tell all it should do is run refresh or refresh-all in between suspend and resume. However, when I do that manually all is okay.

2017-09-05T17:35:04.000665Z

oh, OK - if you are losing access to a running component, it’s not doing that process properly, I was suspicious of suspend and resume because I know that stop and start work, and haven’t used suspend and resume

vinai 2017-09-05T17:35:06.000667Z

Only the cider keyboard shortcut messes the state up.

2017-09-05T17:35:35.000125Z

right, what I was suggesting was hooking onto the keyboard shortcut

2017-09-05T17:35:46.000495Z

because there is nothing you can do easily to make that not break your app

vinai 2017-09-05T17:36:59.000186Z

Currently I'm just invoking reset when I need to manually, but it would be nice to have the keyboard shortcut working... Here are the docs:

(cider-refresh &optional MODE)

Reload modified and unloaded namespaces on the classpath.

With a single prefix argument, or if MODE is `refresh-all', reload all
namespaces on the classpath unconditionally.

With a double prefix argument, or if MODE is `clear', clear the state of
the namespace tracker before reloading.  This is useful for recovering from
some classes of error (for example, those caused by circular dependencies)
that a normal reload would not otherwise recover from.  The trade-off of
clearing is that stale code from any deleted files may not be completely
unloaded.

👍 1
vinai 2017-09-05T17:37:36.000445Z

Maybe I should head over to #cider

vinai 2017-09-05T17:40:40.000312Z

The elisp code in question is

`("op" ,(if refresh-all? "refresh-all" "refresh")
                   "print-length" ,cider-stacktrace-print-length
                   "print-level" ,cider-stacktrace-print-level)
So it really only seems to send the op nrepl message refresh-all or refresh.

vinai 2017-09-05T17:40:51.000086Z

Anyway, thanks for chiming in!