从 Clojure REPL 重新启动 HTTP 服务器的工作流程
我的一个基于 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 上启动服务器,如下所示(编译后< code>web.clj 和 Cc Ck
):
user> (myproject.web/initialize)
每当编辑 web.clj
或其他依赖模块时,我必须
记住不要重新编译
web.clj
使用 Cc Ck,因为保存正在运行的实例的原子会从 REPL 中消失(由于来自新编译模块的原子)。运行
(myproject.web/reinitialize)
,它会停止服务器,然后在再次启动之前重新加载模块。
这样做有两个问题:
我经常忘记第 1 点,但还是按
抄送
。这会导致 REPL 中服务器原子的丢失,导致必须杀死 swank(或重新启动 emacs),以便我可以在相同的端口号启动服务器。:reload-all
不会像Cc Ck
那样友好地报告编译错误(丑陋的回溯与简洁的可点击错误)。
在这个编辑-编译-重启工作流程中如何最好地解决这两个问题?
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.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.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-k
anyway. 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-all
doesn'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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以
用这种方式替换它,它不会重新定义服务器。
当您评估缓冲区时,
You can replace
with
that way when you evaluate the buffer it will not redefine server.
对于第一个问题,您可以将原子存储在不同的命名空间中,并且在加载时仅在尚未定义时覆盖它。将其放入自己的命名空间中将防止其被重新加载全部删除
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