从Clojure REPL重新启动HTTP服务器的工作流程

6
我的一个基于Clojure的项目使用netty(由aleph所需)Web服务器。 我在web.clj文件中启动服务器和其他组件,如下所示:
(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))

服务器实例存储在Clojure的原子(atom)中,以便稍后可以停止它。
我使用Emacs和Swank直接在REPL上启动服务器,像这样(在使用C-c C-k编译web.clj后):
user> (myproject.web/initialize)

无论是编辑web.clj或其他相关的模块时,都必须记住不要使用C-c C-k重新编译web.clj,因为由于新编译的模块中的原子(atom),正在运行的实例会消失(REPL中的原子)。
解决方法如下:
1. 别忘了第一点,不要使用C-c C-k。否则需要杀掉swank进程(或重启emacs),以便在相同的端口号上启动服务器。
2. 运行(myproject.web/reinitialize)停止服务器,并重新加载模块,然后再次启动服务器。
这样做存在两个问题:
1. 经常会忘记第一点,不小心按下C-c C-k。这会导致REPL中的服务器原子(atom)丢失,从而需要杀掉swank进程(或重启emacs)才能在相同的端口号上启动服务器。
2. :reload-all 没有像使用C-c C-k那样友好地报告编译错误(不美观的回溯信息(traceback)与简洁的可点击的错误信息)。
如何在编辑-编译-重新启动的工作流程中最好地解决这两个问题?
2个回答

7

你可以替换

(def server (atom nil))

使用

(defonce server (atom nil))

那样当您评估缓冲区时,它不会重新定义服务器。

2

针对您的第一个问题,您可以将该原子存储在不同的命名空间中,并且仅在加载时覆盖它,如果它尚未定义。将其放置在自己的命名空间中可以防止其被reload-all擦除。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接