Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Implement an auto-reconnect function like slime has #56

Closed
wants to merge 2 commits into from

3 participants

@blais

I often bring down my clojure VM and then back up.
In SLIME there was a variable to do that.
I implemented something similar for nrepl.
I'm not sure doing it in nrepl-current-session is the best idea though.
Thanks,

@technomancy

I wonder if this might be implemented better by supporting an nrepl-disconnect-hook. That way users could make it work either by jacking-in again or by reconnecting to an external process. The implementation in this pull request will only work if the nrepl server is restarted on the same port as before, which usually isn't the case for most people.

@blais

Saving the last connection port is a really nice idea, esp. since lein's repl server appears to use a random port by default (any reason why?).

However, reconnecting on disconnect won't work in the most common case: the VM was killed/bounced. It'll try to reconnect immediately and will fail, because a new VM isn't ready right away. I once had an implementation of this that would kick off on disconnect and used timers to attempt reconnect in the background every second and then with a backoff time delay, but it was just a bit annoying and complicated in different ways. When I discovered slime's ability to just reconnect on eval, it just felt so much more natural.

I think I also want to add some sort of modeline feedback to indicate that the VM is disconnected.

Your comments appreciated.

@technomancy

Right, the idea is that with a hook, users of jack-in can restart the JVM in the case of it exiting unexpectedly, while users who launch the JVM by hand can do something else.

Leiningen's repl uses a random port in order to avoid conflicts and because the underlying port is usually an irrelevant implementation detail during development. Of course you can always override it in a per-project basis.

@kingtim
Owner

I have just added an nrepl-disconnected-hook which is called when the JVM exits.
There is also now an nrepl-restart command which you can use to restart.

Thanks for your contribution!

@kingtim kingtim closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 34 additions and 2 deletions.
  1. +34 −2 nrepl.el
View
36 nrepl.el
@@ -63,6 +63,15 @@
(defvar nrepl-version "0.1.3-preview"
"The current nrepl version.")
+(defvar nrepl-host "localhost"
+ "Default value for hostname to connect to.")
+
+(defvar nrepl-port 4006
+ "Default value for port to connect to.")
+
+(defvar nrepl-auto-reconnect nil
+ "Attempt to reconnect automatically if the connection has failed.")
+
(defface nrepl-prompt-face
'((t (:inherit font-lock-keyword-face)))
"Face for the prompt in the nREPL client."
@@ -1003,8 +1012,17 @@ buffer."
;;; server messages
(defun nrepl-current-session ()
- (with-current-buffer "*nrepl-connection*"
- nrepl-session))
+ (if nrepl-auto-reconnect
+ ;; If the connection buffer cannot be found, attempt synchronously to
+ ;; reconnect and signal an error if that fails.
+ (if (or (get-buffer "*nrepl-connection*") (nrepl-sync-connect))
+ (with-current-buffer "*nrepl-connection*"
+ nrepl-session)
+ (error "Could not auto reconnect."))
+
+ (with-current-buffer "*nrepl-connection*"
+ nrepl-session)) )
+
(defun nrepl-send-request (request callback)
(let* ((request-id (number-to-string (incf nrepl-request-counter)))
@@ -1411,6 +1429,19 @@ under point, prompts for a var."
(nrepl-create-client-session (nrepl-new-session-handler (process-buffer process)))
process))
+
+(defun nrepl-sync-connect ()
+ "Attempts to reconnect and waits for ack.
+Silently returns nil on failure to reconnect."
+ (condition-case e
+ (let ((proc (nrepl-connect nrepl-host nrepl-port)))
+ ;; Wait for the ack for at most 1 second.
+ (when proc (accept-process-output proc 1 0))
+ proc)
+ (file-error nil) ;; Ignore silently, return nil
+ ))
+
+
;;;###autoload
(add-hook 'nrepl-connected-hook 'nrepl-enable-on-existing-clojure-buffers)
@@ -1422,5 +1453,6 @@ under point, prompts for a var."
(process (nrepl-connect "localhost" port)))
(nrepl-init-repl-buffer process nrepl-buffer)))
+
(provide 'nrepl)
;;; nrepl.el ends here
Something went wrong with that request. Please try again.