CIDER nREPL Internals
Lazy middleware loading
Eager loading of all of `cider-nrepl’s middleware resulted in a significant impact to the startup time of the nREPL server. To mitigate this we’ve devised a strategy to postpone the actual initialization of some middleware until the first time it’s actually used by a client.
That’s the reason why middleware description in
cider-nrepl are not following the common
nREPL convention to be supplied in the same file where the middleware is defined.
Dealing with unhandled exception
Even though nREPL requests are asychronous in their nature, some editors might be forced
to wait for the response of a request. This is obviously going to result in lock-up in
case of an unhandled exception, that’s why
cider-nrepl introduced the concept of
a "safe transport" that does some reasonable handling of such errors.
Operating on unresolved symbols
All middleware ops operating on some symbol that needs to be resolved would normally do the
resolution themselves. They typically take as parameters
sym, which are current
namespace and a symbol in it, and would resolve
sym in the context of
This spares users from having to invoke
info on every symbol before passing the resolved result
to another op. It also maps well to the typical editor workflow - normally you’d be asking
for some operation to be performed for some unresolved symbol in the current namespace.
Currently the ClojureScript support relies on inspecting the ClojureScript compiler
cider-nrepl would fetch the compiler state from Piggieback and pass it
to the underlying libraries (e.g.
clj-suitable) that do something useful with it.
Unfortunately the majority of the middlewares don’t support ClojureScript
currently, as they are implemented in terms of Clojure-only libraries. Another
roadblock is that
cider-nrepl runs in a Clojure context and you have to jump
through some hoops to evaluate ClojureScript code from it (e.g. pipe it to
eval or evaluate it against the ClojureScript runtime directly as
a string). Hopefully this will change down the road.
`cider-nrepl’s dependency would conflict with the dependencies of the application using it, so we have to take some care to avoid such situation.
All of cider-nrepl’s dependencies are processed with mranderson, so that they won’t collide with the dependencies of your own projects. This basically means that cider-nrepl doesn’t have any runtime dependencies in the production artifact - just copies of the deps inlined with changed namespaces/packages.
This means that
cider-nrepl has to also take some steps to hide the inlined namespaces,
so they won’t pollute the results users would be interested in. Pretty much all of `cider-nrepl’s
ops would filter out the inlined namespaces.