Closed zonotope closed 7 years ago
At first read, this looks like a tools.namespace bug, not anything related to 'Component'.
What version of tools.namespace are you using?
.cljc
support was added to tools.namespace in the 0.3.0-alpha series. There are still open bugs for cljc support.
I'm using version 0.2.1 of clojure.tools.namespace but, to be clear, I'm not trying reload a ClojureScript system or using a ClojureScript repl; I'm trying to reload a back-end Clojure system from the Clojure repl, but that system has compiled (and static) cljs sources requiring component on the classpath. This is a ring webapp that serves compiled cljs as static resources.
I initially thought this was a bug with c.t.namespace, but I tried requiring other cross platform libs (bouncer and your dependency lib) in my cljs source, and my minimal system didn't exhibit the problem. Component is the only library I've found that kills the Clojure system if it's required in ClojureScript source.
I will give 0.3.0-alpha of c.t.namespace a shot. Is there a bug tracker for that project?
@zonotope Bug tracker for tools.namespace project is here: http://dev.clojure.org/jira/browse/TNS
A second guess I have is that a ClojureScript build process is copying .cljc
files into a resources
directory, thereby confusing tools.namespace's file tracker. It may be possible to fix this by explicitly setting the directories tools.namespace scans with clojure.tools.namespace.repl/set-refresh-dirs
.
I still don't know why 'Component' specifically would be affected differently from other libraries.
I'm compiling Clojurescript files into my resources
directly, and can confirm setting refresh directories resolved the issue for me.
(clojure.tools.namespace.repl/set-refresh-dirs "src" "test")
Thank you, @stuartsierra.
Update: Only temporarily. After running another refresh my component system is broken again.
Update 2: If I disable reloading of the following namespaces things look good again.
(doseq [sym ['com.stuartsierra.component
'com.stuartsierra.dependency]
:let [ns (find-ns sym)]
:when ns]
(clojure.tools.namespace.repl/disable-reload! ns))
I have not been able reproduce this issue so far. There are so many variables in how projects get set up. And a description like "my component system is broken" doesn't help me much.
If, as I suspect, this is caused by the interaction of tools.namespace and the ClojureScript compiler, then there is likely nothing I can do about it except add a warning to the documentation.
If someone can provide an isolated test case, I would appreciate it. Here's what I need: a complete sample project with only the minimum pieces necessary to reproduce this problem and precise instructions for running it to provoke the failure. Make it as small as possible. Please omit anything that can be omitted and still demonstrate the failure: other libraries, frameworks, tools, plugins, templates, or application code.
Hi @stuartsierra,
I apologise for not providing something easier to work with in my previous comment. I thought I'd found a solution and wanted to share it with others in case it could help someone out.
I don't have a sample project to share (yet), but I have been able to identify a repeatable process that corrupts my system by going from this. It involves refreshing namespaces via Cider's cider-refresh
(I'm jacking in via cider-jack-in
).
What I mean by corrupts/breaks is the dependencies are all nil
, and only values I merge in with merge-with merge
are present:
#inno.listener.Listener{:clients nil, :host "0.0.0.0", :port 3000, :server nil, :socket nil, :session nil}
The listener component should have a :server
and :session
; both of which come from component/system-using
:
(defn make-system
[]
(component/system-using
(component/system-map
:bootstrapper (bootstrap/map->Bootstrapper {})
:listener (listener/map->Listener {})
:timbre (timbre/map->Logger {})
:session (listener/map->Session {})
:socket (listener/map->Socket {}))
{:bootstrapper [:logger]
:listener [:session :socket]}))
I'll cut up my project and see if I can get a minimal test case to surface exactly what the problem is (I think it may be down to Cider's refresh as running (clojure.tools.namespace.repl/refresh)
works as expected).
In fact, now I vaguely remember an issue with the way Cider vendors its dependencies that meant I couldn't set refresh dirs in the past… I'll post back when I have more info.
Update: Even with refresh dirs set in my dev/user.clj
Cider is reloading dependencies it shouldn't be.
cider-refresh: Reloading (inno.ws inno.bootstrap taoensso.sente.interfaces taoensso.sente.packers.transit taoensso.sente inno.listener inno.timbre inno.system inno.config user inno.main)
The Sente namespaces should not be reloaded.
Possibly-related tools.namespace ticket: http://dev.clojure.org/jira/browse/TNS-45
@stuartsierra I can confirm that the problem I am seeing is due to that tools.namespace ticket you linked above.
The suggested workaround using set-refresh-dirs
fixes the problem for me. Executing the following form from my user
namespace (or any other namespace loaded by the repl) works for me:
(clojure.tools.namespace.repl/set-refresh-dirs "dev" "src" "test")
I am closing this issue as it is not a component bug.
If you call
(clojure.tools.namespace.repl/refresh)
in a project repl which contains clj and cljs source that both requirecom.stuartsierra.component
, the function call is reported as successful, but it doesn't seem as if any namespaces are actually reloaded after they're unloaded.The quickest way to reproduce the problem is using the duct template:
Then put the following in
src/cljs/tester/core.cljs
Then, back at the shell:
Visiting localhost:3000 gives a welcome page, but after calling
(do (stop) (refresh) (start))
at the repl, no connections to the web server can be established even though all the functions return either:ok
or:started
with no error.If you kill the repl, run
lein clean
, and modify the above clojurescript source so that the component library isn't required, everything works as expected.It looks like the problem comes from unloading and reloading the component library while there is compiled clojurescript code that uses component on the classpath. If I modify
clojure.tools.namespace.reload/track-reload-one
to skip both unloading and reloading the component namespace during refresh calls, everything works fine then.