我的基于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 and Swank直接在REPL上启动服务器(在使用web.clj
编译C-c C-k
后):
user> (myproject.web/initialize)
每当编辑web.clj
或其他相关模块时,我必须
请记住不要使用C-c C-k重新编译web.clj
,因为持有正在运行的实例的原子会从REPL中消失(由于来自新编译模块的原子)。
运行(myproject.web/reinitialize)
,停止服务器,然后重新加载模块,然后重新启动。
这有两个问题:
我经常忘记第一点,然后按C-c C-k
。这导致REPL中服务器原子丢失,导致必须杀死swank(或重启emacs),以便我可以在相同的端口号启动服务器。
:reload-all
不会将编译错误报告为与C-c C-k
一样友好(丑陋的追溯与简明的可点击错误)。
如何在编辑 - 编译 - 重启工作流程中最好地解决这两个问题?
答案 0 :(得分:6)
您可以替换
(def server (atom nil))
与
(defonce server (atom nil))
当您评估缓冲区时,它不会重新定义服务器。
答案 1 :(得分:2)
对于您的第一个问题,您可以将原子存储在不同的命名空间中,并且在加载时仅覆盖它(如果尚未定义)。将它放在它自己的namepspace中会阻止它被reload-all
删除