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

发布于 2024-12-07 20:02:35 字数 1688 浏览 6 评论 0原文

我的一个基于 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 或其他依赖模块时,我必须

  1. 记住不要重新编译web.clj 使用 Cc Ck,因为保存正在运行的实例的原子会从 REPL 中消失(由于来自新编译模块的原子)。

  2. 运行(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

  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:

  • 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 as C-c C-k (ugly traceback vs concise clickable errors).

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

就像说晚安 2024-12-14 20:02:35

您可以

(def server (atom nil))

用这种方式替换它,它不会重新定义服务器。

(defonce server (atom nil))

当您评估缓冲区时,

You can replace

(def server (atom nil))

with

(defonce server (atom nil))

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

燃情 2024-12-14 20:02:35

对于第一个问题,您可以将原子存储在不同的命名空间中,并且在加载时仅在尚未定义时覆盖它。将其放入自己的命名空间中将防止其被重新加载全部删除

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文