Compare commits
15 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47e55fe5e7 | ||
|
|
717cef7af5 | ||
|
|
cd968459a7 | ||
|
|
8b717eb001 | ||
|
|
6ad6045b94 | ||
|
|
b00133ca05 | ||
|
|
64ecb94de8 | ||
|
|
d29cf6aa65 | ||
|
|
1635931483 | ||
|
|
75c2216649 | ||
|
|
c2e3d8f8b8 | ||
|
|
16bea5b7db | ||
|
|
85c554e643 | ||
|
|
4fb0da7daf | ||
|
|
76313a7089 |
10 changed files with 189 additions and 68 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -3,3 +3,7 @@
|
|||
.lein-failures
|
||||
/pom.xml
|
||||
.lein-repl-history
|
||||
.cache
|
||||
.clj-kondo/babashka
|
||||
.clj-kondo/rewrite-clj
|
||||
src/scratch.clj
|
||||
|
|
|
|||
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,13 +1,20 @@
|
|||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
- [#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
|
||||
- [#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
|
||||
|
||||
- #61: add transit as explicit JVM dependency
|
||||
- #60: transform pod reader error into exception of caller
|
||||
- Switch "out" and "err" messages to print and flush instead of `println` (@justone)
|
||||
- Set TCP_NODELAY on transport socket (@retrogradeorbit)
|
||||
- Allow env vars OS_NAME & OS_ARCH to override os props (@cap10morgan)
|
||||
- #49: don't log socket closed exception
|
||||
- [#61](https://github.com/babashka/pods/issues/61): add transit as explicit JVM dependency
|
||||
- [#60](https://github.com/babashka/pods/issues/60): transform pod reader error into exception of caller
|
||||
- Switch "out" and "err" messages to print and flush instead of `println` ([@justone](https://github.com/justone))
|
||||
- Set TCP_NODELAY on transport socket ([@retrogradeorbit](https://github.com/retrogradeorbit))
|
||||
- Allow env vars OS_NAME & OS_ARCH to override os props ([@cap10morgan](https://github.com/cap10morgan))
|
||||
- [#49](https://github.com/babashka/pods/issues/49): don't log socket closed exception
|
||||
|
||||
## v0.1.0
|
||||
|
||||
|
|
|
|||
39
README.md
39
README.md
|
|
@ -77,7 +77,7 @@ On the JVM:
|
|||
When calling `load-pod` with a string or vector of strings (or declaring it in your `bb.edn`),
|
||||
the pod is looked up on the local file system (either using the PATH, or using an absolute path).
|
||||
When it is called with a qualified symbol and a version - like `(load-pod 'org.babashka/aws "0.0.5")`
|
||||
then it will be looked up in and downloaded from the [pod-registry](https://github.com/babashka/pod-registry).
|
||||
then it will be looked up in and downloaded from the [pod-registry](https://github.com/babashka/pod-registry). You can customize the file system location that `load-pod` will use by setting the `BABASHKA_PODS_DIR` environment variable.
|
||||
|
||||
By default babashka will search for a pod binary matching your system's OS and arch. If you want to download
|
||||
pods for a different OS / arch (e.g. for deployment to servers), you can set one or both of the following
|
||||
|
|
@ -130,7 +130,7 @@ light weight replacement for native interop (JNI, JNA, etc.).
|
|||
|
||||
### Examples
|
||||
|
||||
Beyond the already available pods mentioned above, eductional examples of pods
|
||||
Beyond the already available pods mentioned above, educational examples of pods
|
||||
can be found [here](examples):
|
||||
|
||||
- [pod-lispyclouds-sqlite](examples/pod-lispyclouds-sqlite): a pod that
|
||||
|
|
@ -228,7 +228,7 @@ JSON. It also declares that the pod exposes one namespace,
|
|||
|
||||
To encode payloads in EDN use `"edn"` and for Transit JSON use `"transit+json"`.
|
||||
|
||||
The pod encodes the above map to bencode and writes it to stdoud. The pod client
|
||||
The pod encodes the above map to bencode and writes it to stdout. The pod client
|
||||
reads this message from the pod's stdout.
|
||||
|
||||
Upon receiving this message, the pod client creates these namespaces and vars.
|
||||
|
|
@ -376,11 +376,15 @@ nil
|
|||
|
||||
#### 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
|
||||
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
|
||||
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`:
|
||||
|
||||
|
|
@ -392,6 +396,33 @@ For example, a pod can define a function called `add`:
|
|||
"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
|
||||
|
||||
When your pod exposes multiple namespaces that can be used independently from
|
||||
|
|
|
|||
17
script/changelog.clj
Executable file
17
script/changelog.clj
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bb
|
||||
|
||||
(ns changelog
|
||||
(:require [clojure.string :as str]))
|
||||
|
||||
(let [changelog (slurp "CHANGELOG.md")
|
||||
replaced (str/replace changelog
|
||||
#" #(\d+)"
|
||||
(fn [[_ issue after]]
|
||||
(format " [#%s](https://github.com/babashka/pods/issues/%s)%s"
|
||||
issue issue (str after))))
|
||||
replaced (str/replace replaced
|
||||
#"@([a-zA-Z0-9-_]+)([, \.)])"
|
||||
(fn [[_ name after]]
|
||||
(format "[@%s](https://github.com/%s)%s"
|
||||
name name after)))]
|
||||
(spit "CHANGELOG.md" replaced))
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
(defn bytes->string [^"[B" bytes]
|
||||
(String. bytes))
|
||||
|
||||
(defn bytes->boolean [^"[B" bytes]
|
||||
(= "true" (String. bytes)))
|
||||
|
||||
(defn get-string [m k]
|
||||
(-> (get m k)
|
||||
bytes->string))
|
||||
|
|
@ -36,6 +39,10 @@
|
|||
(some-> (get m k)
|
||||
bytes->string))
|
||||
|
||||
(defn get-maybe-boolean [m k]
|
||||
(some-> (get m k)
|
||||
bytes->boolean))
|
||||
|
||||
(defn next-id []
|
||||
(str (java.util.UUID/randomUUID)))
|
||||
|
||||
|
|
@ -83,10 +90,12 @@
|
|||
(let [wh (transit/write-handler tag-fn val-fn)]
|
||||
(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)]
|
||||
(let [w (transit/writer baos :json {:handlers (get @transit-write-handler-maps pod-id)
|
||||
:default-handler (get @transit-default-write-handlers pod-id)})]
|
||||
(let [w (transit/writer baos :json (cond-> {:handlers (get @transit-write-handler-maps pod-id)
|
||||
:default-handler (get @transit-default-write-handlers pod-id)}
|
||||
metadata? (assoc :transform transit/write-meta)))]
|
||||
(transit/write w s)
|
||||
(str baos))))
|
||||
|
||||
|
|
@ -98,7 +107,7 @@
|
|||
write-fn (case format
|
||||
:edn pr-str
|
||||
: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)
|
||||
chan (if handlers handlers
|
||||
(promise))
|
||||
|
|
@ -128,11 +137,12 @@
|
|||
edn/read-string)
|
||||
name-sym (if vmeta
|
||||
(with-meta name-sym vmeta)
|
||||
name-sym)]
|
||||
name-sym)
|
||||
metadata? (get-maybe-boolean var "arg-meta")]
|
||||
[name-sym
|
||||
(or code
|
||||
(fn [& args]
|
||||
(let [res (invoke pod sym args {:async async?})]
|
||||
(let [res (invoke pod sym args {:async async? :arg-meta metadata?})]
|
||||
res)))]))
|
||||
vars))
|
||||
|
||||
|
|
@ -310,7 +320,8 @@
|
|||
(catch java.net.SocketException _ nil)))
|
||||
|
||||
(defn port-file [pid]
|
||||
(io/file (str ".babashka-pod-" pid ".port")))
|
||||
(doto (io/file (str ".babashka-pod-" pid ".port"))
|
||||
(.deleteOnExit)))
|
||||
|
||||
(defn read-port [^java.io.File port-file]
|
||||
(loop []
|
||||
|
|
|
|||
|
|
@ -91,7 +91,10 @@
|
|||
^"[Ljava.nio.file.CopyOption;"
|
||||
(into-array
|
||||
[java.nio.file.StandardCopyOption/REPLACE_EXISTING])))
|
||||
(sh "tar" "xf" (.getPath tmp-file) "--directory" (.getPath destination-dir))
|
||||
(.mkdirs destination-dir)
|
||||
(let [res (sh "tar" "xf" (.getPath tmp-file) "--directory" (.getPath destination-dir))]
|
||||
(when-not (zero? (:exit res))
|
||||
(throw (ex-info (:err res) res))))
|
||||
(.delete tmp-file)))
|
||||
|
||||
(defn make-executable [dest-dir executables verbose?]
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@
|
|||
(defn- process-namespace [{:keys [:name :vars]}]
|
||||
(binding [*ns* (load-string (format "(ns %s) *ns*" name))]
|
||||
(doseq [[var-sym v] vars]
|
||||
(when-let [maybe-core (some-> (ns-resolve *ns* var-sym) meta :ns str symbol)]
|
||||
(when (= 'clojure.core maybe-core)
|
||||
(ns-unmap *ns* var-sym)))
|
||||
(cond
|
||||
(ifn? v)
|
||||
(do
|
||||
(ns-unmap *ns* var-sym)
|
||||
(intern name var-sym v))
|
||||
(intern name var-sym v)
|
||||
(string? v)
|
||||
(load-string v)))))
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@
|
|||
(transit/write w s)
|
||||
(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]
|
||||
(let [format (cond (contains? cli-args "--json") :json
|
||||
(contains? cli-args "--transit+json") :transit+json
|
||||
|
|
@ -130,6 +136,10 @@
|
|||
{"name" "read-other-tag"
|
||||
"code" "(defn read-other-tag [x] [x x])"
|
||||
"meta" "{:doc \"unread\"}"}
|
||||
{"name" "round-trip-meta"
|
||||
"arg-meta" "true"}
|
||||
{"name" "dont-round-trip-meta"
|
||||
"arg-meta" "false"}
|
||||
{"name" "-local-date-time"}
|
||||
{"name" "transit-stuff"
|
||||
"code" "
|
||||
|
|
@ -176,65 +186,81 @@
|
|||
pod.test-pod/add-sync
|
||||
(try (let [ret (apply + args)]
|
||||
(write out
|
||||
{"value" (write-fn ret)
|
||||
"id" id
|
||||
"status" ["done"]}))
|
||||
{"value" (write-fn ret)
|
||||
"id" id
|
||||
"status" ["done"]}))
|
||||
(catch Exception e
|
||||
(write out
|
||||
{"ex-data" (write-fn {:args args})
|
||||
"ex-message" (.getMessage e)
|
||||
"status" ["done" "error"]
|
||||
"id" id})))
|
||||
{"ex-data" (write-fn {:args args})
|
||||
"ex-message" (.getMessage e)
|
||||
"status" ["done" "error"]
|
||||
"id" id})))
|
||||
pod.test-pod/range-stream
|
||||
(let [rng (apply range args)]
|
||||
(doseq [v rng]
|
||||
(write out
|
||||
{"value" (write-fn v)
|
||||
"id" id})
|
||||
{"value" (write-fn v)
|
||||
"id" id})
|
||||
(Thread/sleep 100))
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
pod.test-pod/assoc
|
||||
(write out
|
||||
{"value" (write-fn (apply assoc args))
|
||||
"status" ["done"]
|
||||
"id" id})
|
||||
{"value" (write-fn (apply assoc args))
|
||||
"status" ["done"]
|
||||
"id" id})
|
||||
pod.test-pod/error
|
||||
(write out
|
||||
{"ex-data" (write-fn {:args args})
|
||||
"ex-message" (str "Illegal arguments")
|
||||
"status" ["done" "error"]
|
||||
"id" id})
|
||||
{"ex-data" (write-fn {:args args})
|
||||
"ex-message" (str "Illegal arguments")
|
||||
"status" ["done" "error"]
|
||||
"id" id})
|
||||
pod.test-pod/print
|
||||
(do (write out
|
||||
{"out" (with-out-str (prn args))
|
||||
"id" id})
|
||||
{"out" (with-out-str (prn args))
|
||||
"id" id})
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
pod.test-pod/print-err
|
||||
(do (write out
|
||||
{"err" (with-out-str (prn args))
|
||||
"id" id})
|
||||
{"err" (with-out-str (prn args))
|
||||
"id" id})
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
{"status" ["done"]
|
||||
"id" id}))
|
||||
pod.test-pod/return-nil
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"value" (write-fn nil)})
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"value" (write-fn nil)})
|
||||
pod.test-pod/reader-tag
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"value" "#my/tag[1 2 3]"})
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"value" "#my/tag[1 2 3]"})
|
||||
pod.test-pod/other-tag
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"value" "#my/other-tag[1]"})
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"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
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
|
|
@ -255,20 +281,20 @@
|
|||
(case ns
|
||||
pod.test-pod.loaded
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"name" "pod.test-pod.loaded"
|
||||
"vars" [{"name" "loaded"
|
||||
"code" "(defn loaded [x] (inc x))"}]})
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"name" "pod.test-pod.loaded"
|
||||
"vars" [{"name" "loaded"
|
||||
"code" "(defn loaded [x] (inc x))"}]})
|
||||
pod.test-pod.loaded2
|
||||
(write out
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"name" "pod.test-pod.loaded2"
|
||||
"vars" [{"name" "x"
|
||||
"code" "(require '[pod.test-pod.loaded :as loaded])"}
|
||||
{"name" "loaded"
|
||||
"code" "(defn loaded [x] (loaded/loaded x))"}]}))
|
||||
{"status" ["done"]
|
||||
"id" id
|
||||
"name" "pod.test-pod.loaded2"
|
||||
"vars" [{"name" "x"
|
||||
"code" "(require '[pod.test-pod.loaded :as loaded])"}
|
||||
{"name" "loaded"
|
||||
"code" "(defn loaded [x] (loaded/loaded x))"}]}))
|
||||
(recur)))))))
|
||||
(catch Exception e
|
||||
(binding [*out* *err*]
|
||||
|
|
|
|||
|
|
@ -84,6 +84,21 @@
|
|||
(.isArray (class v)))
|
||||
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])
|
||||
(def should-be-1 (only-code/foo))
|
||||
|
||||
|
|
@ -116,6 +131,9 @@
|
|||
fn-called
|
||||
local-date-time
|
||||
assoc-string-array
|
||||
round-trip-meta
|
||||
round-trip-meta-nested
|
||||
dont-round-trip-meta
|
||||
should-be-1
|
||||
add-sync-meta
|
||||
error-meta
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
3
|
||||
true ;; local-date
|
||||
true ;; roundtrip string array
|
||||
true ;; roundtrip metadata
|
||||
true ;; roundtrip metadata nested
|
||||
true ;; dont roundtrip metadata (when arg-meta "false"/ absent)
|
||||
1
|
||||
"add the arguments"
|
||||
nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue