I have a bunch of reitit routes defined within a hierarchy of namespaces. When I make a change somewhere deep in the hierarchy, it’s not enough to simply stop and restart the system with integrant.repl/restart because each level up the hierarchy of the nested routes needs to pick up the changes, each needs to be re-`def`ined. Restarting the REPL takes too long. My solution was to open each of the files along the chain in side-by-side tabs (I’m using VS Code and Calva), and then use keyboard shortcuts to quickly evaluate the file, flip to the next tab, and keep going until I had hit them all. Then restart integrant.
What a pain. Today I thought, “there has to be a better way.” So I poked around a bit and came up with this:
(comment
(require 'acme.routes.api.deeply.nested
'acme.routes.api.deeply
'acme.routes.api
'acme.router
:reload)
Now I evaluate that form and then restart integrant. This solution is way less clunky that what I was doing, but there are probably still better ways to go about it. I’m curious, how do you all solve this?Are you doing anything unusual with requires? Integrant-REPL uses tools.namespace for reloading, and that looks for ns declarations in order to build up a dependency graph, so if you have dependencies between files outside of that (via require, load, etc.) then it won't be able to detect them.
I’m not doing anything unusual with requires (outside of rich comments). They are all in very plain, vanilla ns declarations. I have moved these files around as I was settling on the ns hierarchy. Does integrant-repl have any sort of cache that might be out of sync, something I should wipe out and let it rebuild?
So I tried something, totally based on guessing, not on any knowledge I have of how things actually work. I wiped out the .cpcache folder in my project and then restarted everything. I tested adding a simple log message in one of my functions (way down in the hierarchy) and then refreshed the browser and it worked! So maybe this wasn’t integrant-repl per se, but something clogged in the classpath cache. (or something like that, I don’t even really know what I’m talking about…)
I spoke (wrote) too soon. I went and retested on the same stuff that was giving me trouble before, and it still doesn’t refresh correctly. I still have to execute that require with :refresh to get things to work.
Could you explain a little further what the problem is? The integrant-repl library will reload any changed files in dependency order; it shouldn't matter how deeply nested they are. Are you using a source directory other than src? If so you'll need to configure the source directories you're using.
This was the specific problem I was experiencing: I had routes and functions that depended on each other in this chain:
eauth.clj -> forgot.clj -> api.clj -> router.clj
If I made a change to a middleware function in eauth.clj that was then used in a route definition in forgot.clj, I restart the system and go test on the website and the changes in eauth.clj are not picked up. It wasn’t until I manually loaded/eval’d each file, starting with eauth.clj and working upwards towards router.clj, and then restart the system, that I would finally see the changes.
This used to work before when I had my routes defined as functions but lately I’ve been declaring them as def’s and I don’t know but that seems to be about when I lost the automatic refresh magic.Source directory is src.
I think it is solved. I had this note in my user namespace:
;; NOTE: for now, we define our own `reset` (instead of the integrant-provided
;; one) because namespace reloading is choking on our use of `:as-alias` and
;; thinks it is finding a circular dependency (it is not). Might be because
;; integrant is using an older version of tools.namespace (v1.0) and the support
;; for not reloading :as-alias namespaces is 1.3. TODO: check again if this has
;; been resolved in later versions already.
(defn reset []
(halt)
(go))
I update integrant-repl to the latest version, which is using the latest version of tools.namespace and refresh/reload is now working.Glad you found the root cause!