parent
64ecb94de8
commit
b00133ca05
6 changed files with 144 additions and 55 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
- [#63](https://github.com/babashka/pods/issues/63): create directory before un-tarring
|
- [#63](https://github.com/babashka/pods/issues/63): create directory before un-tarring
|
||||||
- [#59](https://github.com/babashka/pods/issues/59): delete port file on exit
|
- [#59](https://github.com/babashka/pods/issues/59): delete port file on exit
|
||||||
- [#65](https://github.com/babashka/pods/issues/65): fix warnings when defining var with core name in JVM
|
- [#65](https://github.com/babashka/pods/issues/65): fix warnings when defining var with core name in JVM
|
||||||
|
- [#66](https://github.com/babashka/pods/issues/66): Allow metadata on fn arguments for transit+json
|
||||||
|
|
||||||
## v0.2.0
|
## v0.2.0
|
||||||
|
|
||||||
|
|
|
||||||
33
README.md
33
README.md
|
|
@ -376,11 +376,15 @@ nil
|
||||||
|
|
||||||
#### Metadata
|
#### Metadata
|
||||||
|
|
||||||
|
**From pod to pod client**
|
||||||
|
|
||||||
|
*Fixed Metadata on vars*
|
||||||
|
|
||||||
Pods may attach metadata to functions and macros by sending data to the pod client
|
Pods may attach metadata to functions and macros by sending data to the pod client
|
||||||
in a `"meta"` field as part of a `"var"` section. The metadata must be an appropriate
|
in a `"meta"` field as part of a `"var"` section. The metadata must be an appropriate
|
||||||
map, encoded as an EDN string. This is only applicable to vars in the pod and will be
|
map, encoded as an EDN string. This is only applicable to vars in the pod and will be
|
||||||
ignored if the var refers to Client-side code, since metadata can already be defined
|
ignored if the var refers to Client-side code, since metadata can already be defined
|
||||||
in those code blocks.
|
in those code blocks (see 'Dynamic Metadata' below to enable the encoding of metadata).
|
||||||
|
|
||||||
For example, a pod can define a function called `add`:
|
For example, a pod can define a function called `add`:
|
||||||
|
|
||||||
|
|
@ -392,6 +396,33 @@ For example, a pod can define a function called `add`:
|
||||||
"meta" "{:doc \"arithmetic addition of 2 arguments\" :arglists ([a b])}"}]}]}
|
"meta" "{:doc \"arithmetic addition of 2 arguments\" :arglists ([a b])}"}]}]}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*Dynamic Metadata*
|
||||||
|
|
||||||
|
Pods may send metadata on values returned to the client if metadata encoding is enabled
|
||||||
|
for the particular transport format used by the pod.
|
||||||
|
|
||||||
|
For example, if your pod uses `:transit+json` as its format, you can enable metadata
|
||||||
|
encoding by adding `:transform transit/write-meta` (or whatever transit is aliased to)
|
||||||
|
to the optional map passed to `transit/writer`. e.g.:
|
||||||
|
|
||||||
|
````clojure
|
||||||
|
(transit/writer baos :json {:transform transit/write-meta})
|
||||||
|
````
|
||||||
|
|
||||||
|
##### From pod client to pod
|
||||||
|
|
||||||
|
Currently sending metadata on arguments passed to a pod function is available only for the
|
||||||
|
`transit+json` format and can be enabled on a per var basis.
|
||||||
|
|
||||||
|
A pod can enable metadata to be read on arguments by sending the "arg-meta" field to "true"
|
||||||
|
for the var representing that function. For example:
|
||||||
|
|
||||||
|
````clojure
|
||||||
|
{:format :transit+json
|
||||||
|
:namespaces [{:name "pod.babashka.demo"
|
||||||
|
:vars [{"name" "round-trip" "arg-meta" "true"}]}]}
|
||||||
|
````
|
||||||
|
|
||||||
#### Deferred namespace loading
|
#### Deferred namespace loading
|
||||||
|
|
||||||
When your pod exposes multiple namespaces that can be used independently from
|
When your pod exposes multiple namespaces that can be used independently from
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@
|
||||||
(defn bytes->string [^"[B" bytes]
|
(defn bytes->string [^"[B" bytes]
|
||||||
(String. bytes))
|
(String. bytes))
|
||||||
|
|
||||||
|
(defn bytes->boolean [^"[B" bytes]
|
||||||
|
(= "true" (String. bytes)))
|
||||||
|
|
||||||
(defn get-string [m k]
|
(defn get-string [m k]
|
||||||
(-> (get m k)
|
(-> (get m k)
|
||||||
bytes->string))
|
bytes->string))
|
||||||
|
|
@ -36,6 +39,10 @@
|
||||||
(some-> (get m k)
|
(some-> (get m k)
|
||||||
bytes->string))
|
bytes->string))
|
||||||
|
|
||||||
|
(defn get-maybe-boolean [m k]
|
||||||
|
(some-> (get m k)
|
||||||
|
bytes->boolean))
|
||||||
|
|
||||||
(defn next-id []
|
(defn next-id []
|
||||||
(str (java.util.UUID/randomUUID)))
|
(str (java.util.UUID/randomUUID)))
|
||||||
|
|
||||||
|
|
@ -83,10 +90,12 @@
|
||||||
(let [wh (transit/write-handler tag-fn val-fn)]
|
(let [wh (transit/write-handler tag-fn val-fn)]
|
||||||
(swap! transit-default-write-handlers assoc *pod-id* wh)))
|
(swap! transit-default-write-handlers assoc *pod-id* wh)))
|
||||||
|
|
||||||
(defn transit-json-write [pod-id ^String s]
|
(defn transit-json-write
|
||||||
|
[pod-id ^String s metadata?]
|
||||||
(with-open [baos (java.io.ByteArrayOutputStream. 4096)]
|
(with-open [baos (java.io.ByteArrayOutputStream. 4096)]
|
||||||
(let [w (transit/writer baos :json {:handlers (get @transit-write-handler-maps pod-id)
|
(let [w (transit/writer baos :json (merge {:handlers (get @transit-write-handler-maps pod-id)
|
||||||
:default-handler (get @transit-default-write-handlers pod-id)})]
|
:default-handler (get @transit-default-write-handlers pod-id)}
|
||||||
|
(when metadata? {:transform transit/write-meta})))]
|
||||||
(transit/write w s)
|
(transit/write w s)
|
||||||
(str baos))))
|
(str baos))))
|
||||||
|
|
||||||
|
|
@ -97,8 +106,8 @@
|
||||||
chans (:chans pod)
|
chans (:chans pod)
|
||||||
write-fn (case format
|
write-fn (case format
|
||||||
:edn pr-str
|
:edn pr-str
|
||||||
:json cheshire/generate-string
|
:json cheshire/generate-string
|
||||||
:transit+json #(transit-json-write (:pod-id pod) %))
|
:transit+json #(transit-json-write (:pod-id pod) % (:arg-meta opts)))
|
||||||
id (next-id)
|
id (next-id)
|
||||||
chan (if handlers handlers
|
chan (if handlers handlers
|
||||||
(promise))
|
(promise))
|
||||||
|
|
@ -128,11 +137,12 @@
|
||||||
edn/read-string)
|
edn/read-string)
|
||||||
name-sym (if vmeta
|
name-sym (if vmeta
|
||||||
(with-meta name-sym vmeta)
|
(with-meta name-sym vmeta)
|
||||||
name-sym)]
|
name-sym)
|
||||||
|
metadata? (get-maybe-boolean var "arg-meta")]
|
||||||
[name-sym
|
[name-sym
|
||||||
(or code
|
(or code
|
||||||
(fn [& args]
|
(fn [& args]
|
||||||
(let [res (invoke pod sym args {:async async?})]
|
(let [res (invoke pod sym args {:async async? :arg-meta metadata?})]
|
||||||
res)))]))
|
res)))]))
|
||||||
vars))
|
vars))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,12 @@
|
||||||
(transit/write w s)
|
(transit/write w s)
|
||||||
(str baos))))
|
(str baos))))
|
||||||
|
|
||||||
|
(defn transit-json-write-meta [s]
|
||||||
|
(with-open [baos (java.io.ByteArrayOutputStream. 4096)]
|
||||||
|
(let [w (transit/writer baos :json {:transform transit/write-meta})]
|
||||||
|
(transit/write w s)
|
||||||
|
(str baos))))
|
||||||
|
|
||||||
(defn run-pod [cli-args]
|
(defn run-pod [cli-args]
|
||||||
(let [format (cond (contains? cli-args "--json") :json
|
(let [format (cond (contains? cli-args "--json") :json
|
||||||
(contains? cli-args "--transit+json") :transit+json
|
(contains? cli-args "--transit+json") :transit+json
|
||||||
|
|
@ -130,6 +136,10 @@
|
||||||
{"name" "read-other-tag"
|
{"name" "read-other-tag"
|
||||||
"code" "(defn read-other-tag [x] [x x])"
|
"code" "(defn read-other-tag [x] [x x])"
|
||||||
"meta" "{:doc \"unread\"}"}
|
"meta" "{:doc \"unread\"}"}
|
||||||
|
{"name" "round-trip-meta"
|
||||||
|
"arg-meta" "true"}
|
||||||
|
{"name" "dont-round-trip-meta"
|
||||||
|
"arg-meta" "false"}
|
||||||
{"name" "-local-date-time"}
|
{"name" "-local-date-time"}
|
||||||
{"name" "transit-stuff"
|
{"name" "transit-stuff"
|
||||||
"code" "
|
"code" "
|
||||||
|
|
@ -176,65 +186,81 @@
|
||||||
pod.test-pod/add-sync
|
pod.test-pod/add-sync
|
||||||
(try (let [ret (apply + args)]
|
(try (let [ret (apply + args)]
|
||||||
(write out
|
(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 out
|
(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"]
|
||||||
"id" id})))
|
"id" id})))
|
||||||
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 out
|
(write out
|
||||||
{"value" (write-fn v)
|
{"value" (write-fn v)
|
||||||
"id" id})
|
"id" id})
|
||||||
(Thread/sleep 100))
|
(Thread/sleep 100))
|
||||||
(write out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
"id" id}))
|
"id" id}))
|
||||||
pod.test-pod/assoc
|
pod.test-pod/assoc
|
||||||
(write out
|
(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 out
|
(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 out
|
(do (write out
|
||||||
{"out" (with-out-str (prn args))
|
{"out" (with-out-str (prn args))
|
||||||
"id" id})
|
"id" id})
|
||||||
(write out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
"id" id}))
|
"id" id}))
|
||||||
pod.test-pod/print-err
|
pod.test-pod/print-err
|
||||||
(do (write out
|
(do (write out
|
||||||
{"err" (with-out-str (prn args))
|
{"err" (with-out-str (prn args))
|
||||||
"id" id})
|
"id" id})
|
||||||
(write out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
"id" id}))
|
"id" id}))
|
||||||
pod.test-pod/return-nil
|
pod.test-pod/return-nil
|
||||||
(write out
|
(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 out
|
(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 out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
"id" id
|
"id" id
|
||||||
"value" "#my/other-tag[1]"})
|
"value" "#my/other-tag[1]"})
|
||||||
|
pod.test-pod/round-trip-meta
|
||||||
|
(write out
|
||||||
|
{"status" ["done"]
|
||||||
|
"id" id
|
||||||
|
"value"
|
||||||
|
(case format
|
||||||
|
:transit+json (transit-json-write-meta (first args))
|
||||||
|
(write-fn (first args)))})
|
||||||
|
pod.test-pod/dont-round-trip-meta
|
||||||
|
(write out
|
||||||
|
{"status" ["done"]
|
||||||
|
"id" id
|
||||||
|
"value"
|
||||||
|
(case format
|
||||||
|
:transit+json (transit-json-write-meta (first args))
|
||||||
|
(write-fn (first args)))})
|
||||||
pod.test-pod/-local-date-time
|
pod.test-pod/-local-date-time
|
||||||
(write out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
|
|
@ -255,20 +281,20 @@
|
||||||
(case ns
|
(case ns
|
||||||
pod.test-pod.loaded
|
pod.test-pod.loaded
|
||||||
(write out
|
(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 out
|
(write out
|
||||||
{"status" ["done"]
|
{"status" ["done"]
|
||||||
"id" id
|
"id" id
|
||||||
"name" "pod.test-pod.loaded2"
|
"name" "pod.test-pod.loaded2"
|
||||||
"vars" [{"name" "x"
|
"vars" [{"name" "x"
|
||||||
"code" "(require '[pod.test-pod.loaded :as loaded])"}
|
"code" "(require '[pod.test-pod.loaded :as loaded])"}
|
||||||
{"name" "loaded"
|
{"name" "loaded"
|
||||||
"code" "(defn loaded [x] (loaded/loaded x))"}]}))
|
"code" "(defn loaded [x] (loaded/loaded x))"}]}))
|
||||||
(recur)))))))
|
(recur)))))))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(binding [*out* *err*]
|
(binding [*out* *err*]
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,21 @@
|
||||||
(.isArray (class v)))
|
(.isArray (class v)))
|
||||||
true))
|
true))
|
||||||
|
|
||||||
|
(def round-trip-meta
|
||||||
|
(if (= "transit+json" fmt)
|
||||||
|
(= {:my-meta 2} (meta (pod.test-pod/round-trip-meta (with-meta [2] {:my-meta 2}))))
|
||||||
|
true))
|
||||||
|
|
||||||
|
(def round-trip-meta-nested
|
||||||
|
(if (= "transit+json" fmt)
|
||||||
|
(= {:my-meta 3} (meta (first (pod.test-pod/round-trip-meta [(with-meta [3] {:my-meta 3})]))))
|
||||||
|
true))
|
||||||
|
|
||||||
|
(def dont-round-trip-meta
|
||||||
|
(if (= "transit+json" fmt)
|
||||||
|
(= nil (meta (pod.test-pod/dont-round-trip-meta (with-meta [2] {:my-meta 2}))))
|
||||||
|
true))
|
||||||
|
|
||||||
(require '[pod.test-pod.only-code :as only-code])
|
(require '[pod.test-pod.only-code :as only-code])
|
||||||
(def should-be-1 (only-code/foo))
|
(def should-be-1 (only-code/foo))
|
||||||
|
|
||||||
|
|
@ -116,6 +131,9 @@
|
||||||
fn-called
|
fn-called
|
||||||
local-date-time
|
local-date-time
|
||||||
assoc-string-array
|
assoc-string-array
|
||||||
|
round-trip-meta
|
||||||
|
round-trip-meta-nested
|
||||||
|
dont-round-trip-meta
|
||||||
should-be-1
|
should-be-1
|
||||||
add-sync-meta
|
add-sync-meta
|
||||||
error-meta
|
error-meta
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@
|
||||||
3
|
3
|
||||||
true ;; local-date
|
true ;; local-date
|
||||||
true ;; roundtrip string array
|
true ;; roundtrip string array
|
||||||
|
true ;; roundtrip metadata
|
||||||
|
true ;; roundtrip metadata nested
|
||||||
|
true ;; dont roundtrip metadata (when arg-meta "false"/ absent)
|
||||||
1
|
1
|
||||||
"add the arguments"
|
"add the arguments"
|
||||||
nil
|
nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue