Heyo. I have a question. it seems that the view of messages in nREPL varies depending on whether I looking at them from a middleware, or from a client
I'm trying to write a function that takes a piece of code as a string and evaulates it, returning all nREPL messages related to it's evauluation
And for standard responses, it's fine
But anything sent to err or out doesn't seem to arrive on the client side
Which is unfortunate, because I am trying to write code for modifying error messages, and those don't show up
*err*
and *out*
are thread local bindings, so writing to them will depend on what thread the writing to is occuring on
if in your server process you are spinning up some thread that somehow doesn't copy the repls values of *err*
and *out*
it will get the default values and nrepl won't be able to capture the output
So this is what I have.
(defn trap-response [inp-code]
(with-open [conn (repl/connect :port server-port)]
(-> (repl/client conn 1000)
(repl/message {:op :eval :code inp-code})
doall)))
With some code to start an nREPL server preceding it
In the middleware I am trying to test, I know that
:err
existshow can I copy the repl values of
*err*
?it will depend on what you are running and what inp-code is doing
e.g. a new thread launched with say future
does automatically inherit the initiating threads values of err and out (also any other dynamic vars bound)
if you are manually creating and starting a Thread object you will have do it yourself, the easiest way is likely to use bound-fn
hmm
for the present I am not doing anyhting threaded
oh, are you saying your middleware is seeing the messages with :err
in them?
Yeah
My middleware is attempting to improve java error messages
just somewhere between your middleware and the client the message is getting dropped
is your middleware forwarding on the message correctly? is it throwing an error causing the error message to be swallowed?
Yeah, and the error message comes through, but as a print, and not in right place
what do you mean "as a print" and "not in the right place" ?
one moment
Okay, so I run trap response and I get a list of nrepl messages back
But it also prints the modified error message
so I get something like
teardown.core=> (trap-response "(banana)")
Name banana is undefined.
({:ex "class clojure.lang.Compiler$CompilerException", :id "a71b6465-6515-4b66-801c-91daa498cdf8", :root-ex "class clojure.lang.Compiler$CompilerException", :session "50e928a8-2fed-44c9-adae-8404972586f1", :status ["eval-error"]} {:id "a71b6465-6515-4b66-801c-91daa498cdf8", :session "50e928a8-2fed-44c9-adae-8404972586f1", :status ["done"]})
teardown.core=>
oh, that isn't :err
okay
that is :ex , the exception value
status :eval-error
yeah.
that isn't output to *out*
or *err*
, that is the error result of the eval
I would like to see an entry in my list of responses with that key
are you just printing the message in your middleware?
no
what does trap-response do?
https://clojurians.slack.com/archives/C17JYSA3H/p1524254777000128 this is the definition of trap response
and what does your middleware do? are you running the repl server in the same jvm as you are running trap-response?
my middleware takes the value of :err and changes it. Eventually I hope to gain access to the exception object, but for the moment I am parsing string to string
are you sure you aren't just printing out the string in the middleware? it looks a lot like you are
I am not sure that an error like that results in anything coming back with :errr
set
I think you just get the :ex
no, there are no prints in my middleware
middleware wraps the transport function in incoming messages, so that post eval this code is run
(defn modify-errors "takes a nREPL response, and returns a message with the errors fixed"
[inp-message]
(if (contains? inp-message :err)
(assoc inp-message :err (m-obj/get-all-text (:msg-info-obj (p-exc/process-spec-errors (inp-message :err)))))
inp-message))
I am looking at the interruptible-eval middleware right now, and when an exception is thrown it doesn't set :err
, you get back the :ex
message
and yet my middleware works. I don't mean to be obtuse, but in developping the middleware I never got access to the
:ex
messagehow recently have you restarted your repl?
fresh for these commands
Fresh everytime I touched the middleware
I would put in some printlns in each branch of that if to see which branch is actually getting taken
https://github.com/UnwarySage/babel/tree/demo-work/src/babel
This is the code
and I know which branch is being taken, because I can see the transformed error messages
no, you are seeing some printlns
okay. I am confused but attentive
you are seeing some output that sort of looks like it matches what in some circumstances might match what you would get if your middelware is running
but that doesn't actually prove that it is, so you need to prove that it is, and prove that is running the way you expect
you may also have an easier time debugging this kind of thing if you run the client and the server in different jvms
I can do that.
Well, I can connect to the babel jvm
what do you mean by that?
I am unsure of how to connect to a nREPL server using the middleware
I mean, you have two jvms, on running an nrepl server with your middleware, a second running an nrepl server without your middleware, you nrepl into the second and run trap-response
(connecting to the first)
will try
where you see the message printed out will tell you if it is being printed in the client side or the server side
it is almost certainly on the server side
IIRC it is, that was what I meant when I said "in the wrong place"
if you are satisfied that you have proved to yourself that it is printing on the server side, then you can start looking at the code being run on the server side
are you aot compiling?
No.
what I am getting at there is, is the code you think you are running what is actually running, aot compilation can be a culprit there, but I've seen people have multiple copies of the src directory and edit the wrong one, or forget to save the file, or whatever
Okay, so launching one repl with middleware, connecting a second one to it, defining and running trap response in the second one gets me a modified error message and the return list of messages, both in the second repl
interesting
waitaminute.
trap-response launches a third repl server and sends things to it for eval
How but the error messages are still being modified
so...
I think I see
my kind of vague hand wavy guess is you have state issues in your middleware stack, global state is being used, which could be a problem if you have more than one nrepl session running
somehow between the repl trap response runs and the one it is in, my middleware steps in
I don't think there is any state
I dunno, I see a bunch of def'ed atoms, and I made a hand wavy guess
in core?
yes
sorry core has been deprecated. Those were for testing purposes, and no code runs in core now.
really sorry about that
no worries, just took a glance around
So, just trying out a plain old division by zero error in the repl that runs trap-response, I see it's error messages are being modified
https://clojurians.slack.com/archives/C17JYSA3H/p1524256604000032 though I am still concerned by any problems you saw when you said this
I didn't see any problems, it is more like like I try to eliminate assumptions when debugging, and that seemed like one
fair enough
AFK ~2 minutes max
back
okay
it seems if trap-response's own server is set to point at the modified server, then I do get
:err
This seems to be working, and I am very grateful
thank you for your time and expertise