Fork me on GitHub
#dirac
<
2019-01-23
>
jmromrell19:01:03

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

jmromrell19:01:32

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)))

jmromrell19:01:32

In my repl I can see:

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

darwin19:01:35

can you copy what Dirac Agent prints during start?

jmromrell19:01:46

I don't see any logs printed on startup.

jmromrell19:01:50

From dirac, at least

darwin19:01:15

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

darwin19:01:12

Dirac Agent v1.3.0
Connected to nREPL server at .
Agent is accepting connections at .

jmromrell19:01:17

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

jmromrell19:01:34

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

darwin19:01:52

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

jmromrell19:01:18

[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})

darwin19:01:04

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

jmromrell19:01:42

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

darwin19:01:58

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

darwin19:01:20

and AFAIK session is handled by nrepl session middleware

jmromrell19:01:40

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

jmromrell19:01:20

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

jmromrell19:01:23

Let me see if I can fix that

darwin19:01:53

it expects some previous code was wrapped in ensure-session

darwin19:01:18

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

darwin19:01:34

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

darwin19:01:05

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

darwin19:01:40

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

darwin19:01:50

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

jmromrell19:01:52

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

jmromrell19:01:15

Running things again, hopefully it all works now

darwin19:01:57

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

jmromrell19:01:01

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

jmromrell19:01:39

Looks like it is all working now. Thank you!

darwin19:01:41

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

jmromrell19:01:32

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

jmromrell19:01:46

However, after maybe a minute it will show:

jmromrell19:01:49

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.

jmromrell19:01:59

With this printed on server:

jmromrell19:01:03

[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}

jmromrell19:01:34

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

jmromrell19:01:29

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

darwin19:01:16

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

darwin19:01:09

ah, it will be more involved

darwin19:01:14

not just the env var

jmromrell19:01:55

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

jmromrell19:01:01

Meanwhile, another hopefully quick question:

jmromrell19:01:40

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

jmromrell19:01:10

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

jmromrell19:01:55

I don't get this behavior in the figwheel repl

darwin19:01:33

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

jmromrell20:01:12

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

jmromrell20:01:28

Which appears to follow the first instructions you linked

darwin20:01:33

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

darwin20:01:08

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

darwin20:01:24

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

darwin20:01:18

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

jmromrell20:01:25

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?

darwin20:01:11

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

darwin20:01:06

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

jmromrell20:01:53

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).

jmromrell20:01:06

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

jmromrell20:01:23

Thanks for the awesome tool! 🙂

darwin20:01:37

np, good luck 🙂

darwin20:01:07

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”