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

欢迎!请参阅关于页面以了解更多有关此工作方式的信息。

0
REPL

TLDR:我如何启动一个“一次性使用”的远程-prepl连接,该连接执行单个命令,获取返回值,然后释放所有使用的资源?

我在Slack上询问了这个问题,但没有收到回复。在实际情况中,这通常不是一个大问题,但我一直在为此烦恼,所以我决定更正式地记录在这里。

我曾以为短生命周期的远程-prepl客户端是一个预期的使用方式。它应该允许用户连接到远程系统,执行某个操作,获取返回值,然后断开连接。

以下是一些我找到的示例代码:
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)")

我发现无法通过关闭所用的流来获取“ 完成”输出,这标志着停止prepl线程循环。无论关闭流的组合多么复杂,都无法实现。

稍加查看远程-prepl的源代码,它似乎会在这一行调用关闭reader的操作,但它将在reader已经关闭时调用。但至少在上述示例中,我发现当第二次调用close时,这会导致事情永远挂起。我猜这与https://stackoverflow.com/a/45703662中描述的问题有关,与PipedReader/Writer的设置有关。

但我不确定这是否可以被认为是prepl代码中的错误,或者是我使用方法不对。

1 答案

0
我尝试了最新的补丁(包含对 Printwriter-On 的修改)以及该线程中描述的“(binding [*out* *err*] (flush))”的“技巧解决方案”。不幸的是,这两个对我都不起作用。这很可能与之相关。我将在不久的将来花更多时间研究并反馈。
...