2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解如何运作的更多信息。

0 投票
REPL

简答:我该如何启动一个“一次性使用”的远程预处理器连接,仅运行单个命令,获取返回值然后释放所有使用资源?

我在 Slack 上提问了,但没有收到回答。虽然在实际应用中这通常不是一个大问题,但它一直在困扰着我,所以我决定在这里正式记录下来。

我之前一直认为短期高效远程预处理器客户端是一个预期用途。它应该允许连接到远程服务器,执行一些操作,获取返回值然后断开连接。

我找到了一些这方面的示例代码,在这里
https://github.com/Olical/how-to-be-a-repl-sorcerer/blob/b6bd530f3d0c6b165248d980d7ce6cd28e8da51f/src/sorcery/main.clj#L20

略有修改

(ns prepl-question
  (:require [clojure.core.server :as server])
  (:import [java.io PipedReader PipedWriter]))

(def srv
  (server/start-server {:accept 'clojure.core.server/io-prepl
                        :port   0
                        :name   "srv"}))

(defn remote-eval [code]
  (with-open [reader (PipedReader.)
              writer (PipedWriter.)]
    (.connect reader writer)
    (let [result! (promise)]
      (future
        (server/remote-prepl
          "localhost" (.getLocalPort srv)
          reader
          (fn [msg]
            (deliver result! msg)))
        (println "DONE"))
      (.write writer code)
      (.flush writer)
      @result!

      ;; doesn't print "DONE"
      (let [r @result!]
        (.close reader)
        (.close writer)

        ;;(.write writer ":repl/quit\n") ;; also tried this
        ;;(.flush writer)

        r))))

(remote-eval "(+ 1 2 3)")

我发现无法通过关闭使用中的任何流组合来打印 "DONE",这表明需要停止预处理器线程循环。

通过一点点的查看远程预处理器源代码,看上去这里的一行代码将会调用读取器的 close 方法,但是读取器在使用前已经关闭了。但至少在上述示例中,我发现第二次调用 close 会导致永久挂起。我猜这与https://stackoverflow.com/a/45703662中描述的问题有关,该问题涉及 PipedReader/Writer 设置。

但我并不确定这可否被视为预处理器代码中的错误,或者是不是我用错了。

1 答案

0 投票
by
我试过了最新的补丁(带有Printwriter-On更改)以及thread中描述的`(binding [*out* *err*] (flush))`“黑客解决方案”。遗憾的是,这对我都没有起作用。但它可能与之相关。我很快会花更多时间研究,并回来报告。
...