dirac

Dirac v1.7.2 is out: https://github.com/binaryage/dirac/releases/tag/v1.7.2
jmromrell 2019-01-23T19:22:03.008Z

I am trying to get dirac working with my app, but am getting the error "Dirac Agent is not listening at <ws://localhost:8231>"

jmromrell 2019-01-23T19:22:32.008500Z

My app uses mount, and I am starting the dirac agent like so:

(mount/defstate ^{:on-reload :noop} repl-server
  :start
  (when (env :nrepl-port)
    (dirac.agent/boot!)
    (nrepl/start {:bind (env :nrepl-bind)
                  :port (env :nrepl-port)
                  :handler (nrepl.server/default-handler dirac.nrepl/middleware)}))
  :stop
  (when repl-server
    (dirac.agent/destroy!)
    (nrepl/stop repl-server)))

jmromrell 2019-01-23T19:23:32.009Z

In my repl I can see:

@dirac.agent/current-agent
=&gt; #object[clojure.lang.Atom 0x63c0dbd6 {:status :ready, :val nil}]

2019-01-23T19:23:35.009200Z

can you copy what Dirac Agent prints during start?

jmromrell 2019-01-23T19:23:46.009400Z

I don't see any logs printed on startup.

jmromrell 2019-01-23T19:23:50.009600Z

From dirac, at least

2019-01-23T19:24:15.010100Z

then (dirac.agent/boot!) didn’t do its job, it should tell you that it is listening on 8231

2019-01-23T19:25:12.010700Z

Dirac Agent v1.3.0
Connected to nREPL server at <nrepl://localhost:8230>.
Agent is accepting connections at <ws://localhost:8231>.

jmromrell 2019-01-23T19:26:17.011300Z

Aha, now I am getting an exception from dirac I wasn't seeing before.

jmromrell 2019-01-23T19:26:34.011800Z

Does (dirac.agent/boot!) have to be called after the nrepl is started?

2019-01-23T19:26:52.012200Z

no, it runs a background thread which tries to connect repeatedly

jmromrell 2019-01-23T19:27:18.012400Z

[clojure-agent-send-off-pool-9] ERROR nrepl.misc - (#error {
 :cause nil
 :via
 [{:type java.lang.NullPointerException
   :message nil
   :at [clojure.core$swap_BANG_ invokeStatic core.clj 2346]}]
 :trace
 [[clojure.core$swap_BANG_ invokeStatic core.clj 2346]
  [clojure.core$swap_BANG_ invoke core.clj 2337]
  [dirac.nrepl.state$register_last_seen_nrepl_message_BANG_ invokeStatic state.clj 52]
  [dirac.nrepl.state$register_last_seen_nrepl_message_BANG_ invoke state.clj 49]
  [dirac.nrepl.state$register_last_seen_nrepl_message_BANG_ invokeStatic state.clj 50]
  [dirac.nrepl.state$register_last_seen_nrepl_message_BANG_ invoke state.clj 49]
  [dirac.nrepl.piggieback$handler_job_BANG_ invokeStatic piggieback.clj 93]
  [dirac.nrepl.piggieback$handler_job_BANG_ invoke piggieback.clj 92]
  [dirac.nrepl.piggieback$dirac_nrepl_middleware_handler invokeStatic piggieback.clj 104]
  [dirac.nrepl.piggieback$dirac_nrepl_middleware_handler invoke piggieback.clj 100]
  [clojure.core$partial$fn__5561 invoke core.clj 2616]
  [nrepl.middleware$wrap_conj_descriptor$fn__47766 invoke middleware.clj 15]
  [nrepl.server$handle_STAR_ invokeStatic server.clj 17]
  [nrepl.server$handle_STAR_ invoke server.clj 14]
  [nrepl.server$handle$fn__48186 invoke server.clj 26]
  [clojure.core$binding_conveyor_fn$fn__5476 invoke core.clj 2022]
  [clojure.lang.AFn call AFn.java 18]
  [java.util.concurrent.FutureTask run FutureTask.java 266]
  [java.util.concurrent.ThreadPoolExecutor runWorker ThreadPoolExecutor.java 1142]
  [java.util.concurrent.ThreadPoolExecutor$Worker run ThreadPoolExecutor.java 617]
  [java.lang.Thread run Thread.java 745]]} Unhandled REPL handler exception processing message {:id f181b5ef-f5af-4b46-b28c-89eefe77b65e, :op describe})

2019-01-23T19:29:36.012700Z

hmm

2019-01-23T19:30:04.013200Z

my wild guess is that you don’t have standard nrepl middleware present or in wrong order

jmromrell 2019-01-23T19:30:42.013500Z

(nrepl/start {:bind (env :nrepl-bind)
                  :port (env :nrepl-port)
                  :handler (nrepl.server/default-handler dirac.nrepl/middleware)})

2019-01-23T19:30:58.014100Z

it picks codepath when it expectes nrepl session to be present, but it is nil

2019-01-23T19:31:20.014700Z

and AFAIK session is handled by nrepl session middleware

jmromrell 2019-01-23T19:31:40.015100Z

Let me see if I can grok where this falls in relation to nrepl middleware

jmromrell 2019-01-23T19:32:20.015600Z

Ah, I think you are right and this middleware is being called before nrepl session middleware

jmromrell 2019-01-23T19:32:23.015800Z

Let me see if I can fix that

2019-01-23T19:32:32.016100Z

btw. this is the problematic line: https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/state.clj#L50

2019-01-23T19:32:53.016600Z

it expects some previous code was wrapped in ensure-session

2019-01-23T19:34:18.017200Z

btw. here are more details: https://github.com/binaryage/dirac/blob/master/docs/about-repls.md#clojure-nrepl-sessions I don’t even remember them, the code is pretty old and I forgot the details

2019-01-23T19:34:34.017500Z

For this trick to work our 'session' middleware must be configured to go first (or very early before 'eval' middleware).

2019-01-23T19:38:05.018400Z

I have some sanity checks in during nrepl startup, for example I check for this list of “middleware operations” present (also their order matters): https://github.com/binaryage/dirac/blob/master/src/lib/dirac/lib/nrepl_tunnel.clj#L97-L98

2019-01-23T19:38:40.019300Z

it should give you this warning during startup if your middleware list is non-standard: https://github.com/binaryage/dirac/blob/master/src/lib/dirac/lib/nrepl_tunnel.clj#L68

2019-01-23T19:38:50.019800Z

I guess in your case it failed even before it got there

jmromrell 2019-01-23T19:38:52.019900Z

I'm getting the right message printed, and just resolved a warning about mismatch nrepl version

jmromrell 2019-01-23T19:39:15.020400Z

Running things again, hopefully it all works now

2019-01-23T19:39:57.021200Z

good, maybe I should make that swap more resilient for this case, I’m pretty sure it would print that warning later

jmromrell 2019-01-23T19:42:01.021800Z

Indication that the middleware must come after nrepl session in either error or installation instructions would have probably helped quite a bit

jmromrell 2019-01-23T19:42:39.022Z

Looks like it is all working now. Thank you!

2019-01-23T19:43:41.022900Z

nice, let me know if anything, I don’t personally use boot, so I would be curious if it worked end-to-end

jmromrell 2019-01-23T19:48:32.024600Z

When I stop and then restart the server (and dirac agent) using mount, I see the dirac console correctly stall waiting on the agent, and then reconnect and allow use again

jmromrell 2019-01-23T19:48:46.025Z

However, after maybe a minute it will show:

jmromrell 2019-01-23T19:48:49.025200Z

Unable to bootstrap ClojureScript REPL due to a timeout.
Usually this happens when server-side process raised an exception or crashed.
Please check error output in Dirac Agent.

jmromrell 2019-01-23T19:48:59.025400Z

With this printed on server:

jmromrell 2019-01-23T19:49:03.025600Z

[async-dispatch-3] WARN dirac.lib.weasel-server - Received eval result without matching eval-id #2
[async-dispatch-8] ERROR dirac.lib.nrepl-tunnel-server - [NREPLTunnelServer#3 of [NREPLTunnel#3]] Received a bootstrap timeout from client [WebSocketServerClient#11] :
 {:op :bootstrap-timeout}

jmromrell 2019-01-23T19:49:34.026200Z

It does allow use and return correct responses for about a minute until that occurs, however

jmromrell 2019-01-23T19:51:29.027700Z

This is after closing both the nrepl server using nrepl/stop and the dirac agent using dirac.agent/destroy! before starting both again with nrepl/start and dirac.agent/boot! respectively

2019-01-23T19:51:50.028Z

try to enable verbose logging vie env var: https://github.com/binaryage/dirac/blob/master/docs/faq.md#how-to-enable-debug-logging-in-dirac-agent

2019-01-23T19:52:16.028600Z

we will see just agent side of the communication, but it could help

2019-01-23T19:53:09.029Z

ah, it will be more involved

2019-01-23T19:53:14.029400Z

not just the env var

jmromrell 2019-01-23T19:56:55.029700Z

I have a meeting in a few minutes. I will have to revisit this.

jmromrell 2019-01-23T19:57:01.029900Z

Meanwhile, another hopefully quick question:

jmromrell 2019-01-23T19:57:16.030100Z

jmromrell 2019-01-23T19:57:40.030700Z

Autocomplete recognizes that I have added the require [reagent.session :as session]

jmromrell 2019-01-23T19:58:10.031Z

However, if I try to utilize the alias I see:

jmromrell 2019-01-23T19:58:55.031500Z

I don't get this behavior in the figwheel repl

2019-01-23T19:59:19.031700Z

look here: https://github.com/binaryage/dirac-sample#hello-world

2019-01-23T19:59:33.032200Z

you have to require the stuff first for REPL environment to be aware of it

jmromrell 2019-01-23T20:00:12.032800Z

In my first screenshot you can see that I changed ns to the one with the dependency

jmromrell 2019-01-23T20:00:28.033400Z

Which appears to follow the first instructions you linked

2019-01-23T20:00:33.033600Z

short answer: figwheel uses the same clojurescript compiler state as your live reloading

2019-01-23T20:01:08.034200Z

in-ns will just set current ns, but won’t load code which should be in it

2019-01-23T20:01:24.034600Z

your REPL is a blank slate in case of Dirac (or any other repl except figwheel)

2019-01-23T20:02:18.035500Z

I was also surprised when I first learned about it, maybe you can somehow load all your namespaces as part of your nREPL startup

jmromrell 2019-01-23T20:03:25.036600Z

I think that makes sense now. Are you aware of an easy way to execute all code found in that namespace from within the dirac console?

2019-01-23T20:04:11.037400Z

require will load everything transitively, so if you have one namespace which requires all others that should do the job

2019-01-23T20:05:06.038200Z

you could require that in your REPL init script (I believe) or as your first command before starting working with REPL

jmromrell 2019-01-23T20:06:53.038900Z

All right, for now simply requiring the ns before calling in-ns appears to be sufficient (at least until I start trying to create circular dependencies :D).

jmromrell 2019-01-23T20:07:06.039300Z

I really appreciate all the help. It's looking like this will really improve my workflow

jmromrell 2019-01-23T20:07:23.039600Z

Thanks for the awesome tool! 🙂

2019-01-23T20:07:37.039700Z

np, good luck 🙂

2019-01-23T20:13:07.041100Z

btw. the reason why it sees [reagent.session :as session] is because auto-completion uses just info from source maps, for example tries to parse ns form in associated sourcemap and help this way, it is not related to what nREPL server “thinks”