This commit is contained in:
Michiel Borkent 2020-10-15 10:55:22 +02:00
parent 6fc595392e
commit dd57413d27
4 changed files with 102 additions and 68 deletions

View file

@ -1,11 +1,21 @@
#!/usr/bin/env bash #!/usr/bin/env bash
export BABASHKA_POD_TEST_FORMAT
export BABASHKA_POD_TEST_SOCKET
# format = edn # format = edn
BABASHKA_POD_TEST_FORMAT=edn
clojure -A:test -n babashka.pods.jvm-test clojure -A:test -n babashka.pods.jvm-test
clojure -A:sci:test -n babashka.pods.sci-test clojure -A:sci:test -n babashka.pods.sci-test
# format = json # format = json
export BABASHKA_POD_TEST_FORMAT
BABASHKA_POD_TEST_FORMAT=json BABASHKA_POD_TEST_FORMAT=json
clojure -A:test -n babashka.pods.jvm-test clojure -A:test -n babashka.pods.jvm-test
clojure -A:sci:test -n babashka.pods.sci-test clojure -A:sci:test -n babashka.pods.sci-test
# socket = true
unset BABASHKA_POD_TEST_FORMAT
BABASHKA_POD_TEST_SOCKET=true
clojure -A:test -n babashka.pods.jvm-test
clojure -A:sci:test -n babashka.pods.sci-test

View file

@ -242,11 +242,12 @@
(.inheritIO pb) (.inheritIO pb)
(.redirectError pb java.lang.ProcessBuilder$Redirect/INHERIT)) (.redirectError pb java.lang.ProcessBuilder$Redirect/INHERIT))
_ (doto (.environment pb) _ (doto (.environment pb)
(.put "BABASHKA_POD" "true")) (.put "BABASHKA_POD" "true")
(.put "BABASHKA_POD_SOCKET" (some-> socket str)))
p (.start pb) p (.start pb)
port-file (when socket (port-file (.pid p))) port-file (when socket (port-file (.pid p)))
socket-port (when socket (read-port port-file)) socket-port (when socket (read-port port-file))
[stdin stdout] [socket stdin stdout]
(if socket (if socket
(let [^Socket socket (let [^Socket socket
(loop [] (loop []
@ -255,9 +256,10 @@
nil))] nil))]
sock sock
(recur)))] (recur)))]
[(.getOutputStream socket) [socket
(.getOutputStream socket)
(PushbackInputStream. (.getInputStream socket))]) (PushbackInputStream. (.getInputStream socket))])
[(.getOutputStream p) (java.io.PushbackInputStream. (.getInputStream p))]) [nil (.getOutputStream p) (java.io.PushbackInputStream. (.getInputStream p))])
_ (write stdin {"op" "describe" _ (write stdin {"op" "describe"
"id" (next-id)}) "id" (next-id)})
reply (read stdout) reply (read stdout)
@ -276,7 +278,10 @@
:err *err* :err *err*
:remove-ns remove-ns :remove-ns remove-ns
:readers readers} :readers readers}
_ (add-shutdown-hook! #(destroy pod)) _ (add-shutdown-hook! #(do
(when socket
(close-socket socket))
(destroy pod)))
pod-namespaces (get reply "namespaces") pod-namespaces (get reply "namespaces")
pod-id (or (when-let [ns (first pod-namespaces)] pod-id (or (when-let [ns (first pod-namespaces)]
(get-string ns "name")) (get-string ns "name"))

View file

@ -4,7 +4,8 @@
[cheshire.core :as cheshire] [cheshire.core :as cheshire]
[clojure.edn :as edn] [clojure.edn :as edn]
[clojure.java.io :as io]) [clojure.java.io :as io])
(:import [java.io PushbackInputStream]) (:import [java.io PushbackInputStream]
[java.net ServerSocket])
(:gen-class)) (:gen-class))
(def debug? false) (def debug? false)
@ -14,17 +15,15 @@
(binding [*out* (io/writer "/tmp/log.txt" :append true)] (binding [*out* (io/writer "/tmp/log.txt" :append true)]
(apply println args)))) (apply println args))))
(def stdin (PushbackInputStream. System/in)) (defn write [stream v]
(bencode/write-bencode stream v)
(defn write [v] (flush))
(bencode/write-bencode System/out v)
(.flush System/out))
(defn read-string [^"[B" v] (defn read-string [^"[B" v]
(String. v)) (String. v))
(defn read [] (defn read [stream]
(bencode/read-bencode stdin)) (bencode/read-bencode stream))
(def dependents (def dependents
(for [i (range 10)] (for [i (range 10)]
@ -43,10 +42,26 @@
pr-str) pr-str)
read-fn (if (identical? :json format) read-fn (if (identical? :json format)
#(cheshire/parse-string % true) #(cheshire/parse-string % true)
edn/read-string)] edn/read-string)
socket (= "true" (System/getenv "BABASHKA_POD_SOCKET"))
[in out] (if socket
(let [server (ServerSocket. 0)
port (.getLocalPort server)
pid (.pid (java.lang.ProcessHandle/current))
port-file (io/file (str ".babashka-pod-" pid ".port"))
_ (.addShutdownHook (Runtime/getRuntime)
(Thread. (fn [] (.delete port-file))))
_ (spit port-file
(str port "\n"))
socket (.accept server)
in (PushbackInputStream. (.getInputStream socket))
out (.getOutputStream socket)]
[in out])
[(PushbackInputStream. System/in)
System/out])]
(try (try
(loop [] (loop []
(let [message (try (read) (let [message (try (read in)
(catch java.io.EOFException _ (catch java.io.EOFException _
::EOF))] ::EOF))]
(when-not (identical? ::EOF message) (when-not (identical? ::EOF message)
@ -55,42 +70,42 @@
op (keyword op)] op (keyword op)]
(case op (case op
:describe :describe
(do (write {"format" (if (= format :json) (do (write out {"format" (if (= format :json)
"json" "json"
"edn") "edn")
"readers" {"my/tag" "identity" "readers" {"my/tag" "identity"
;; NOTE: this function is defined later, ;; NOTE: this function is defined later,
;; which should be supported ;; which should be supported
"my/other-tag" "pod.test-pod/read-other-tag"} "my/other-tag" "pod.test-pod/read-other-tag"}
"namespaces" "namespaces"
[{"name" "pod.test-pod" [{"name" "pod.test-pod"
"vars" (into [{"name" "add-sync"} "vars" (into [{"name" "add-sync"}
{"name" "range-stream" {"name" "range-stream"
"async" "true"} "async" "true"}
{"name" "assoc"} {"name" "assoc"}
{"name" "error"} {"name" "error"}
{"name" "print"} {"name" "print"}
{"name" "print-err"} {"name" "print-err"}
{"name" "return-nil"} {"name" "return-nil"}
{"name" "do-twice" {"name" "do-twice"
"code" "(defmacro do-twice [x] `(do ~x ~x))"} "code" "(defmacro do-twice [x] `(do ~x ~x))"}
{"name" "fn-call" {"name" "fn-call"
"code" "(defn fn-call [f x] (f x))"} "code" "(defn fn-call [f x] (f x))"}
{"name" "reader-tag"} {"name" "reader-tag"}
;; returns thing with other tag ;; returns thing with other tag
{"name" "other-tag"} {"name" "other-tag"}
;; reads thing with other tag ;; reads thing with other tag
{"name" "read-other-tag" {"name" "read-other-tag"
"code" "(defn read-other-tag [x] [x x])"}] "code" "(defn read-other-tag [x] [x x])"}]
dependents)} dependents)}
{"name" "pod.test-pod.loaded" {"name" "pod.test-pod.loaded"
"defer" "true"} "defer" "true"}
{"name" "pod.test-pod.loaded2" {"name" "pod.test-pod.loaded2"
"defer" "true"} "defer" "true"}
{"name" "pod.test-pod.only-code" {"name" "pod.test-pod.only-code"
"vars" [{"name" "foo" "vars" [{"name" "foo"
"code" "(defn foo [] 1)"}]}] "code" "(defn foo [] 1)"}]}]
"ops" {"shutdown" {}}}) "ops" {"shutdown" {}}})
(recur)) (recur))
:invoke (let [var (-> (get message "var") :invoke (let [var (-> (get message "var")
read-string read-string
@ -104,12 +119,12 @@
(case var (case var
pod.test-pod/add-sync pod.test-pod/add-sync
(try (let [ret (apply + args)] (try (let [ret (apply + args)]
(write (write out
{"value" (write-fn ret) {"value" (write-fn ret)
"id" id "id" id
"status" ["done"]})) "status" ["done"]}))
(catch Exception e (catch Exception e
(write (write out
{"ex-data" (write-fn {:args args}) {"ex-data" (write-fn {:args args})
"ex-message" (.getMessage e) "ex-message" (.getMessage e)
"status" ["done" "error"] "status" ["done" "error"]
@ -117,50 +132,50 @@
pod.test-pod/range-stream pod.test-pod/range-stream
(let [rng (apply range args)] (let [rng (apply range args)]
(doseq [v rng] (doseq [v rng]
(write (write out
{"value" (write-fn v) {"value" (write-fn v)
"id" id}) "id" id})
(Thread/sleep 100)) (Thread/sleep 100))
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id})) "id" id}))
pod.test-pod/assoc pod.test-pod/assoc
(write (write out
{"value" (write-fn (apply assoc args)) {"value" (write-fn (apply assoc args))
"status" ["done"] "status" ["done"]
"id" id}) "id" id})
pod.test-pod/error pod.test-pod/error
(write (write out
{"ex-data" (write-fn {:args args}) {"ex-data" (write-fn {:args args})
"ex-message" (str "Illegal arguments") "ex-message" (str "Illegal arguments")
"status" ["done" "error"] "status" ["done" "error"]
"id" id}) "id" id})
pod.test-pod/print pod.test-pod/print
(do (write (do (write out
{"out" (pr-str args) {"out" (pr-str args)
"id" id}) "id" id})
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id})) "id" id}))
pod.test-pod/print-err pod.test-pod/print-err
(do (write (do (write out
{"err" (pr-str args) {"err" (pr-str args)
"id" id}) "id" id})
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id})) "id" id}))
pod.test-pod/return-nil pod.test-pod/return-nil
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id "id" id
"value" (write-fn nil)}) "value" (write-fn nil)})
pod.test-pod/reader-tag pod.test-pod/reader-tag
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id "id" id
"value" "#my/tag[1 2 3]"}) "value" "#my/tag[1 2 3]"})
pod.test-pod/other-tag pod.test-pod/other-tag
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id "id" id
"value" "#my/other-tag[1]"})) "value" "#my/other-tag[1]"}))
@ -173,14 +188,14 @@
read-string)] read-string)]
(case ns (case ns
pod.test-pod.loaded pod.test-pod.loaded
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id "id" id
"name" "pod.test-pod.loaded" "name" "pod.test-pod.loaded"
"vars" [{"name" "loaded" "vars" [{"name" "loaded"
"code" "(defn loaded [x] (inc x))"}]}) "code" "(defn loaded [x] (inc x))"}]})
pod.test-pod.loaded2 pod.test-pod.loaded2
(write (write out
{"status" ["done"] {"status" ["done"]
"id" id "id" id
"name" "pod.test-pod.loaded2" "name" "pod.test-pod.loaded2"

View file

@ -3,8 +3,12 @@
(def fmt (or (System/getenv "BABASHKA_POD_TEST_FORMAT") (def fmt (or (System/getenv "BABASHKA_POD_TEST_FORMAT")
"edn")) "edn"))
(def socket (System/getenv "BABASHKA_POD_TEST_SOCKET"))
(def pod-id (:pod/id (pods/load-pod (cond-> ["clojure" "-A:test-pod"] (def pod-id (:pod/id (pods/load-pod (cond-> ["clojure" "-A:test-pod"]
(= "json" fmt) (conj "--json"))))) (= "json" fmt) (conj "--json"))
{:socket (boolean socket)})))
(require '[pod.test-pod :as pod]) (require '[pod.test-pod :as pod])
(def pod-ns-name (ns-name (find-ns 'pod.test-pod))) (def pod-ns-name (ns-name (find-ns 'pod.test-pod)))