Sridhar Ratnakumar
Sridhar Ratnakumar

Reputation: 85392

Workflow for restarting a HTTP server from Clojure REPL

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

  1. remember NOT to recompile web.clj using 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.

  2. Run (myproject.web/reinitialize) which stops the server and then reloads the module before starting it again.

There are two problems with this:

How can I best address these two problems in this edit-compile-restart workflow?

Upvotes: 6

Views: 925

Answers (2)

Hamza Yerlikaya
Hamza Yerlikaya

Reputation: 49329

You can replace

(def server (atom nil))

with

(defonce server (atom nil))

that way when you evaluate the buffer it will not redefine server.

Upvotes: 7

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91554

for your first problem you can store the atom in a different namespace and on load only overwrite it if it is not yet defined. putting it in it's own namepspace will prevent it from being erased by the reload-all

Upvotes: 2

Related Questions