Fork me on GitHub
#nrepl
<
2018-04-20
>
Charlot19:04:47

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

Charlot19:04:30

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

Charlot19:04:49

And for standard responses, it's fine

Charlot19:04:17

But anything sent to err or out doesn't seem to arrive on the client side

Charlot19:04:56

Which is unfortunate, because I am trying to write code for modifying error messages, and those don't show up

hiredman20:04:31

*err* and *out* are thread local bindings, so writing to them will depend on what thread the writing to is occuring on

hiredman20:04:39

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

Charlot20:04:17

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

Charlot20:04:32

With some code to start an nREPL server preceding it

Charlot20:04:06

In the middleware I am trying to test, I know that

:err
exists

Charlot20:04:19

how can I copy the repl values of

*err*
?

hiredman20:04:25

it will depend on what you are running and what inp-code is doing

hiredman20:04:07

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)

hiredman20:04:06

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

Charlot20:04:41

for the present I am not doing anyhting threaded

hiredman20:04:47

oh, are you saying your middleware is seeing the messages with :err in them?

Charlot20:04:11

My middleware is attempting to improve java error messages

hiredman20:04:15

just somewhere between your middleware and the client the message is getting dropped

hiredman20:04:44

is your middleware forwarding on the message correctly? is it throwing an error causing the error message to be swallowed?

Charlot20:04:51

Yeah, and the error message comes through, but as a print, and not in right place

hiredman20:04:10

what do you mean "as a print" and "not in the right place" ?

Charlot20:04:40

one moment

Charlot20:04:42

Okay, so I run trap response and I get a list of nrepl messages back

Charlot20:04:59

But it also prints the modified error message

Charlot20:04:04

so I get something like

Charlot20:04:12

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

hiredman20:04:43

oh, that isn't :err

hiredman20:04:59

that is :ex , the exception value

hiredman20:04:21

status :eval-error

hiredman20:04:58

that isn't output to *out* or *err*, that is the error result of the eval

Charlot20:04:00

I would like to see an entry in my list of responses with that key

hiredman20:04:20

are you just printing the message in your middleware?

hiredman20:04:43

what does trap-response do?

hiredman20:04:12

and what does your middleware do? are you running the repl server in the same jvm as you are running trap-response?

Charlot20:04:50

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

hiredman20:04:35

are you sure you aren't just printing out the string in the middleware? it looks a lot like you are

hiredman20:04:13

I am not sure that an error like that results in anything coming back with :errr set

hiredman20:04:26

I think you just get the :ex

Charlot20:04:28

no, there are no prints in my middleware

Charlot20:04:15

middleware wraps the transport function in incoming messages, so that post eval this code is run

Charlot20:04:35

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

hiredman20:04:35

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

Charlot20:04:16

and yet my middleware works. I don't mean to be obtuse, but in developping the middleware I never got access to the

:ex
message

hiredman20:04:50

how recently have you restarted your repl?

Charlot20:04:28

fresh for these commands

Charlot20:04:43

Fresh everytime I touched the middleware

hiredman20:04:28

I would put in some printlns in each branch of that if to see which branch is actually getting taken

Charlot20:04:10

This is the code

Charlot20:04:30

and I know which branch is being taken, because I can see the transformed error messages

hiredman20:04:55

no, you are seeing some printlns

Charlot20:04:18

okay. I am confused but attentive

hiredman20:04:44

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

hiredman20:04:39

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

hiredman20:04:58

you may also have an easier time debugging this kind of thing if you run the client and the server in different jvms

Charlot20:04:17

I can do that.

Charlot20:04:46

Well, I can connect to the babel jvm

hiredman20:04:28

what do you mean by that?

Charlot20:04:17

I am unsure of how to connect to a nREPL server using the middleware

hiredman20:04:25

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

hiredman20:04:33

(connecting to the first)

hiredman20:04:09

where you see the message printed out will tell you if it is being printed in the client side or the server side

hiredman20:04:24

it is almost certainly on the server side

Charlot20:04:47

IIRC it is, that was what I meant when I said "in the wrong place"

hiredman20:04:34

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

hiredman20:04:40

are you aot compiling?

hiredman20:04:56

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

Charlot20:04:25

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

hiredman20:04:46

interesting

Charlot20:04:56

waitaminute.

Charlot20:04:36

trap-response launches a third repl server and sends things to it for eval

Charlot20:04:56

How but the error messages are still being modified

Charlot20:04:42

I think I see

hiredman20:04:05

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

Charlot20:04:21

somehow between the repl trap response runs and the one it is in, my middleware steps in

Charlot20:04:29

I don't think there is any state

hiredman20:04:53

I dunno, I see a bunch of def'ed atoms, and I made a hand wavy guess

Charlot20:04:27

sorry core has been deprecated. Those were for testing purposes, and no code runs in core now.

Charlot20:04:32

really sorry about that

hiredman20:04:57

no worries, just took a glance around

Charlot20:04:02

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

Charlot20:04:45

https://clojurians.slack.com/archives/C17JYSA3H/p1524256604000032 though I am still concerned by any problems you saw when you said this

hiredman20:04:14

I didn't see any problems, it is more like like I try to eliminate assumptions when debugging, and that seemed like one

Charlot20:04:31

fair enough

Charlot20:04:54

AFK ~2 minutes max

Charlot21:04:52

it seems if trap-response's own server is set to point at the modified server, then I do get

:err

Charlot21:04:43

This seems to be working, and I am very grateful

Charlot21:04:53

thank you for your time and expertise