I've just started development of a service in Clojure. I'm a little lost in how to approach server shutdown.
I'm using Clojure 1.5.1. For logging, I'm using Timbre 1.5.3. I want to embed NREPL into my server for hot code deployment.
This is my core.clj file. Core is my main and I'm using the app shell that "lein new app" generates.
(ns extenium.core
(:require [taoensso.timbre :as t]
[clojure.tools.nrepl.server :as nrs])
(:gen-class))
(def nrepl-server)
(defn start-nrepl-server []
(t/info "Starting nrepl server on port 8628")
(alter-var-root #'nrepl-server
(constantly
(nrs/start-server :port 8628)))
(t/info "Started nrepl server"))
(defn stop-nrepl-server []
(t/info "Stopping nrepl server")
(nrs/stop-server nrepl-server)
(t/info "Stopped nrepl server"))
(defn start []
(alter-var-root #'*read-eval*
(constantly
false))
(start-nrepl-server))
(defn stop []
(stop-nrepl-server))
(defn -main [& args]
(start))
When I "lein run" the nrepl-server starts as expected, with info messages going to the Terminal. I then connect with "nrepl" from Emacs. No problem. From Emacs I execute "(extenium.core/stop)". At that point, I get the "Stopping nrepl server" message on Emacs (meaning that stdout was redirected to the client). The connection closes (as expected) and I never see the "Stopped nrepl server" message. Fine.
I look at the Terminal and I don't see the "Stopping..." or "Stopped..." messages. Instead, I get the following exception:
Exception in thread "nREPL-worker-0" java.lang.Error: java.net.SocketException: Socket closed
Ideally, I want the following:
Disclaimer: I haven't done this, but it seems interesting.
Per the README, specifically the section "Why nREPL?" you should be able to implement 2 - 4 by implementing your own custom transport, perhaps merely extending one of the out-of-the-box ones.
Stopping the server gracefully may entail extending the socket transport. What you are describing as "graceful shutdown" sounds like implementation of a "Logout" protocol.
Authorizing actions they perform seems less straightforward. It looks like you would need to implement a custom Handler, perhaps again wrapping the default-handler
with the authorization code.
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With