Closed cjsauer closed 4 years ago
Hmm. Makes sense. I don't think I intended for the repl namespace to work outside of the synchronous executor.
It would need to participate in the executor somehow. That might be possible, but it's probably unexpected to have an async reset workflow.
One option might be a "synchronize" option to the repl code.
That way we avoid executors getting clever about sometimes synchronizing.
Technically, manifold could synchronize the whole thing by deref'ing and I think that would cover most use cases. That wouldn't work for clojurescript very well though, with the promesa library.
To be completely explicit too, manifold could have its own repl namespace. That makes automated tooling more difficult though.
I think I like the approach of manifold having its own separate repl namespace. Some sort of synchronization would be great. Maybe a dev-only component could be injected into the system config whose sole purpose is to depend on all other components. That would give the repl ns something explicit to sync against.
Right now my workaround is just rolling my own start/stop functionality, and not worrying about syncing.
(def system-config nil)
(def system nil)
(defn start []
(alter-var-root #'system-config (constantly (config/dev-system)))
(alter-var-root #'system (constantly @(clip/start system-config)))
(keys system))
(defn stop []
(alter-var-root #'system
(fn [s]
(when s
@(clip/stop system-config s)))))
(defn reset []
(stop)
(refresh :after 'user/start))
This is pretty sketchy, but it works. My components all log their start/stop status to stdout, so when I run (start)
I just "manually" wait for everything to spin up before trying to poke at the system.
Do you think it's useful to have start be async?
Not personally, no, but my use-cases are limited. I'm not using clip in cljs (browser), for example, where it's prudent to let go of the render thread asap. Async start
makes more sense in that context. Currently I'm only using clip for backend work, which means start
is the "last" thing I call before just waiting on @(promise)
indefinitely, as in your readme example.
Apologies, I mean for the REPL only. I'm thinking that async (reset)
makes no sense. I realize now I missed a @
in your example, I thought your (repl/start)
was async.
Agreed, I don't think it makes sense for (reset)
to be async at the REPL.
I would welcome a PR which:
Allows :juxt.clip.repl/deref
in the system, which is a function/symbol which allows for "synchronizing" the system between runs. Most often it will be deref. If it is a symbol it should be requiring-resolve'd. If the symbol has no namespace, it should be resolved in clojure.core.
Hello 👋
I'm running into an exception using the reloaded REPL convenience namespace with the manifold executor. Here is a minimal repro (note I'm using aero):
When running
(start)
at the REPL, the following exception is thrown: