简答:我该如何启动一个“一次性使用”的远程预处理器连接,仅运行单个命令,获取返回值然后释放所有使用资源?
我在 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 设置。
但我并不确定这可否被视为预处理器代码中的错误,或者是不是我用错了。