Fork me on GitHub
#nrepl
<
2021-01-24
>
Andrey01:01:14

Hi, I have embedded nrepl in my Java application and need to initialize thread that is used to actually evaluate the expression by setting some session context to thread local variable (this approach cannot be changed). I wrote some simple middleware that utilizes long-lived sessions. In this middleware I just wrap the :code prepending it with initialisation of the session context: (defn inject-session-context  [h]  (fn [{:keys [op session transport code] :as msg}]     (if (and session code)       (let [new-code (str "(do (com.example.nrepl.middleware/set-session-context \"" session "\")"  code ")")]         (h (assoc msg :code new-code)))       (h msg)))) It works, but in combination with cider-nrepl middleware disrupts debugging functionality. The only alternative solution (w/o nrepl source modification) that I found so far would be to check thread name, which has format "NREPL-session uuid" when theread local is accessed (it is necessary only in dev. mode), but I'd like to avoid this fragile approach. Maybe there is a better option? Thank you.

bozhidar19:01:02

Btw, what exactly are you aiming to achieve with this middleware? That's not clear to me, so I wanted to clarify this before discussing any potential options/solutions.

Andrey12:01:15

The code that is called directly or indirectly in evaluated expression needs access to session context stored in thread local variable. Session context stores such information as long running hibernate session, login data. Currently as a workaround I just modified evaluate in interruptible-eval:

Andrey12:01:30

:eval (let [eval-fn (if eval (find-var (symbol eval)) (com.example.clojure.nrepl.callbacks/gb-eval-fn session-id))]

Andrey12:01:22

Where gb-eval-fn just initialises session context if it is empty for this session, sets corresponding thread local and performs eval (defn gb-eval-fn  [session-id]  (fn [code]  (do    (when session-id    (set-session-context session-id))    (eval code))))

Andrey12:01:37

I hope I answered the question. Basically there is big legacy java code base that is called by clojure code and it relies on the presence of the session context in the thread local var

Andrey15:01:40

Sorry for pinging @U051BLM8F , will do this only once - not sure how threads notification work. Would appreciate your feedback whenever you have time

bozhidar08:02:55

No worries. Can you open a discussion on the subject https://github.com/nrepl/nrepl/discussions so it'd be less likely that I'll forget about this.

bozhidar08:02:49

Generally it seems to me it'd be preferable for you to modify the session but inserting some middleware before eval instead of modifying eval directly, but I might be missing something. I'm also wondering if this https://github.com/nrepl/nrepl/pull/214 might be something that can be helpful in your case

bozhidar08:02:35

With a configurable thread factory you might be able to move this init logic to it (I presume).

odie10:01:26

Hi all, I updated cider & friends after some time away from clojure. I found that I’m repeatedly getting unhandled exceptions like this:

ERROR: Unhandled REPL handler exception processing message {:op eldoc, ...}
Here’s the startup cmd reported by cider:
;;  Startup: /usr/local/bin/clojure -Sdeps '{:deps {nrepl/nrepl {:mvn/version "0.8.3"} refactor-nrepl {:mvn/version "2.5.0"} cider/cider-nrepl {:mvn/version "0.25.7"}}}' -m nrepl.cmdline --middleware '["refactor-nrepl.middleware/wrap-refactor","cider.nrepl/cider-middleware"]'
Am I missing something really obvious here?

dpsutton17:01:24

Check #cider Someone was just in there reporting this. Hopefully there’s a ticket linked as well

bozhidar19:01:14

@dpsutton @odie We already fixed this on Orchard's master (https://github.com/clojure-emacs/orchard/commit/e3de281fa731ee81c3a012200c0c94b4e2cecded), even though we're not quite sure how something like this might be happening and why it's affecting only some people.