TLDR:我怎样才能启动一个“一次性使用”的远程预处理器连接,该连接运行单个命令,获取返回值,然后释放所有使用的资源?
我曾在 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)")
我发现无论如何关闭使用的流,都无法得到“完成”的打印输出,以表示停止预处理器线程循环。
稍微查看了一下远程预处理器的源代码,看起来这里这句话会关闭读取器,但它将在读取器已经关闭时被调用。但至少在上面提到的例子中,我发现在第二次调用 close 时会导致事情永远挂起。我猜这与在此处描述的问题有关:https://stackoverflow.com/a/45703662,与 PipedReader/Writer 设置相关。
但我不确定这能否被认为是在预处理器代码中的一个错误,或者是我使用它的方式不正确。