Skip to content

Commit

Permalink
[#55,#56] add clojure.core.async
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Sep 7, 2019
1 parent 93f1542 commit 5ca1061
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 9 deletions.
34 changes: 34 additions & 0 deletions README.md
Expand Up @@ -131,6 +131,9 @@ explicitly.
- `sh`
- `clojure.java.io` aliased as `io`:
- `as-relative-path`, `copy`, `delete-file`, `file`
- [`clojure.core.async`](https://clojure.github.io/core.async/) aliased as
`async`. The `alt` and `go` macros are not available but `alts!!` does work as
it is a function.
- [`me.raynes.conch.low-level`](https://github.com/clj-commons/conch#low-level-usage)
aliased as `conch`

Expand Down Expand Up @@ -164,6 +167,20 @@ Waits for TCP connection to be available on host and port. Options map supports
`:timeout` and `:pause`. If `:timeout` is provided and reached, exception will
be thrown. The `:pause` option determines the time waited between retries.

- `sig/pipe-signal-received?`. Usage:

``` clojure
(sig/pipe-signal-received?)
```

Returns true if `PIPE` signal was received. Example:

``` shellsession
$ bb '((fn [x] (println x) (when (not (sig/pipe-signal-received?)) (recur (inc x)))) 0)' | head -n2
1
2
```

## Examples

``` shellsession
Expand Down Expand Up @@ -308,6 +325,23 @@ $ bb '
(net/wait-for-it "localhost" 1777) (conch/destroy ws)'
```

## Async

Apart from `future` for creating threads and the `conch` namespace for creating
processes, you may use `core.async` to script asynchronously. The following
example shows how to get first available value from two different processes:

``` clojure
bb '
(defn async-command [& args]
(async/thread (apply shell/sh "bash" "-c" args)))

(-> (async/alts!! [(async-command "sleep 2 && echo process 1")
(async-command "sleep 1 && echo process 2")])
first :out str/trim println)'
process 2
```

## Enabling SSL

If you want to be able to use SSL to e.g. run `(slurp
Expand Down
3 changes: 2 additions & 1 deletion project.clj
Expand Up @@ -9,7 +9,8 @@
:url "http://opensource.org/licenses/eclipse-1.0.php"}
:source-paths ["src" "sci/src" "sci/inlined" "conch/src"]
:resource-paths ["resources" "sci/resources"]
:dependencies [[org.clojure/clojure "1.10.1"]]
:dependencies [[org.clojure/clojure "1.10.1"]
[org.clojure/core.async "0.4.500"]]
:profiles {:test {:dependencies [[clj-commons/conch "0.9.2"]]}
:uberjar {:global-vars {*assert* false}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"
Expand Down
68 changes: 68 additions & 0 deletions src/babashka/impl/async.clj
@@ -0,0 +1,68 @@
(ns babashka.impl.async
{:no-doc true}
(:require [clojure.core.async :as async]))

(defn thread
[& body]
`(~'async/thread-call (fn [] ~@body)))

(def async-bindings
{'async/<!! async/<!!
'async/>!! async/>!!
'async/admix async/admix
'async/alts! async/alts!
'async/alts!! async/alts!!
'async/buffer async/buffer
'async/chan async/chan
'async/close! async/close!
'async/do-alt async/do-alt
'async/do-alts async/do-alts
'async/dropping-buffer async/dropping-buffer
'async/filter< async/filter<
'async/filter> async/filter>
'async/into async/into
'async/map async/map
'async/map< async/map<
'async/map> async/map>
'async/mapcat< async/mapcat<
'async/mapcat> async/mapcat>
'async/merge async/merge
'async/mix async/mix
'async/mult async/mult
'async/offer! async/offer!
'async/onto-chan async/onto-chan
'async/partition async/partition
'async/partition-by async/partition-by
'async/pipe async/pipe
'async/pipeline async/pipeline
'async/pipeline-async async/pipeline-async
'async/pipeline-blocking async/pipeline-blocking
'async/poll! async/poll!
'async/promise-chan async/promise-chan
'async/pub async/pub
'async/put! async/put!
'async/reduce async/reduce
'async/remove< async/remove<
'async/remove> async/remove>
'async/sliding-buffer async/sliding-buffer
'async/solo-mode async/solo-mode
'async/split async/split
'async/sub async/sub
'async/take async/take
'async/take! async/take!
'async/tap async/tap
'async/thread (with-meta thread {:sci/macro true})
'async/thread-call async/thread-call
'async/timeout async/timeout
'async/to-chan async/to-chan
'async/toggle async/toggle
'async/transduce async/transduce
'async/unblocking-buffer? async/unblocking-buffer?
'async/unique async/unique
'async/unmix async/unmix
'async/unmix-all async/unmix-all
'async/unsub async/unsub
'async/unsub-all async/unsub-all
'async/untap async/untap
'async/untap-all async/untap-all})

28 changes: 23 additions & 5 deletions src/babashka/impl/clojure/core.clj
Expand Up @@ -10,17 +10,35 @@
{;; atoms
'atom atom
'swap! swap!
'swap-vals! swap-vals!
'reset! reset!
'add-watch add-watch

'future-call future-call
'future (with-meta future {:sci/macro true})
'future-cancel future-cancel
'future-cancelled? future-cancelled?
'future-done? future-done?
'future? future?
'deref deref
'agent agent
'send send
'send-off send-off
'promise promise
'deliver deliver
'shutdown-agents shutdown-agents
'run! run!
'slurp slurp
'spit spit
'pmap pmap
'print print
'pr pr
'pr-str pr-str
'prn prn
'prn-str prn-str
'print-str print-str
'print print
'println println
'future-call future-call
'future (with-meta future {:sci/macro true})
'deref deref})
'println-str println-str
'flush flush
'ex-info ex-info
'ex-data ex-data
})
8 changes: 6 additions & 2 deletions src/babashka/main.clj
Expand Up @@ -4,6 +4,7 @@
[babashka.impl.File :refer [file-bindings]]
[babashka.impl.System :refer [system-bindings]]
[babashka.impl.Thread :refer [thread-bindings]]
[babashka.impl.async :refer [async-bindings]]
[babashka.impl.clojure.core :refer [core-bindings]]
[babashka.impl.clojure.stacktrace :refer [print-stack-trace]]
[babashka.impl.conch :refer [conch-bindings]]
Expand Down Expand Up @@ -147,12 +148,14 @@ Everything after that is bound to *command-line-args*."))
'io/file io/file
'io/reader io/reader
'edn/read-string edn/read-string
'net/wait-for-it net/wait-for-it}
'net/wait-for-it net/wait-for-it
'sig/pipe-signal-received? pipe-signal-received?}
core-bindings
system-bindings
file-bindings
thread-bindings
conch-bindings))
conch-bindings
async-bindings))

(defn read-edn []
(edn/read {;;:readers *data-readers*
Expand Down Expand Up @@ -244,6 +247,7 @@ Everything after that is bound to *command-line-args*."))
t1 (System/currentTimeMillis)]
(when time? (binding [*out* *err*]
(println "bb took" (str (- t1 t0) "ms."))))
(flush)
exit-code))

(defn -main
Expand Down
11 changes: 10 additions & 1 deletion test/babashka/main_test.clj
Expand Up @@ -129,7 +129,7 @@
(let [tmp (java.io.File/createTempFile "script" ".clj")]
(spit tmp "(defn foo [x y] (+ x y)) (defn bar [x y] (* x y))")
(is (= "120\n" (test-utils/bb nil (format "(load-file \"%s\") (bar (foo 10 30) 3)"
(.getPath tmp)))))))
(.getPath tmp)))))))

(deftest preloads-test
;; THIS TEST REQUIRES:
Expand Down Expand Up @@ -176,3 +176,12 @@
(net/wait-for-it \"127.0.0.1\" 7171)
(conch/destroy web-server)
(net/wait-for-it \"localhost\" 7172 {:timeout 50})"))))

(deftest async-test
(is (= "process 2\n" (test-utils/bb nil "
(defn async-command [& args]
(async/thread (apply shell/sh \"bash\" \"-c\" args)))
(-> (async/alts!! [(async-command \"sleep 2 && echo process 1\")
(async-command \"sleep 1 && echo process 2\")])
first :out str/trim println)"))))

0 comments on commit 5ca1061

Please sign in to comment.