A Clojure-based project of mine uses the netty (required by aleph) web server. I start the server, along with other components, in a web.clj file like this:
(ns myproject.web)
(def server (atom nil))
(defn initialize []
(if @server
(println "Warning: already initialized")
(let [port 8001]
(println (format "Starting http://localhost:%s/" port))
(swap! server (fn [_] (start-http-server
(wrap-ring-handler app-routes)
{:port port}))))))
(defn shutdown []
(when @server
(do
(println "Shutting down web server")
(@server)
(swap! server (fn [_] nil)))))
(defn reinitialize []
"Run this on the REPL to reload web.clj and restart the web server"
(myproject.web/shutdown)
(use :reload-all 'myproject.web)
(myproject.web/initialize))
The server instance is stored in a Clojure atom, so that it can be stopped later.
I use Emacs and Swank to directly launch the server on the REPL like this (after compiling web.clj with C-c C-k):
user> (myproject.web/initialize)
Whenever web.clj or other dependent modules are edited, I must
remember NOT to recompile
web.cljusing C-c C-k because the atom holding the running instance would vanish (due to the atom from a newly compiled module) from the REPL.Run
(myproject.web/reinitialize)which stops the server and then reloads the module before starting it again.
There are two problems with this:
Often I forget point #1 and press
C-c C-kanyway. This causes the loss of server atom in REPL, leading to having to kill swank (or restart emacs) so that I can start the server at the same port number.:reload-alldoesn't report compile errors as friendly asC-c C-k(ugly traceback vs concise clickable errors).
How can I best address these two problems in this edit-compile-restart workflow?