Hello, everyone!
In every project where I work with a server, I want to be able to start and stop the server from the REPL without too much fuzz.
Objectives:
- Start and stop server from the REPL
- Avoid getting into weird states where the server is still running, but I don’t have a reference to it.
Specific questions:
- Did I manage to write the start and stop functions thread safe?
- Comments on using a promise inside the swap function?
Code:
(ns eu.teod.hello-test
(:gen-class)
(:require [ring.adapter.jetty]))
(defn handler [req]
{:status 200
:headers {"ContentType" "text/html"}
:body "Hello World"})
(defonce server (atom nil))
(defn start-server! [{:keys [port]}]
(let [retval (promise)]
(swap! server
(fn [old-server]
(if old-server
(do (deliver retval ::server-already-running)
old-server)
(do (deliver retval ::server-started)
(ring.adapter.jetty/run-jetty #'handler
{:port port
:join? false})))))
@retval))
(defn stop-server! []
(let [retval (promise)]
(swap! server
(fn [old-server]
(if-not old-server
(do (deliver retval ::server-already-stopped)
old-server)
(do (deliver retval ::server-stopped)
(.stop old-server)
nil))))
@retval))
(comment
(start-server! {:port 3000})
(stop-server!)
)
(defn -main
"I don't do a whole lot ... yet."
[& args]
(start-server! {:port 80}))
Feedback welcome
Teodor