Skip to content

Commit

Permalink
Merge pull request #40 from jesims/JESI-2652
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreTheHunter committed May 15, 2019
2 parents c94ca89 + 114d775 commit 27cda43
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 19 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.31
0.0.32
14 changes: 8 additions & 6 deletions src/io/jesi/backpack/async.cljc
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
(ns io.jesi.backpack.async
#?(:cljs (:require-macros
[io.jesi.backpack.async :refer [when-open go go-try]]))
#?(:cljs (:require-macros [io.jesi.backpack.async :refer [when-open go go-try]]))
(:require
[clojure.core.async :as async]
[clojure.core.async.impl.protocols :as proto]
[io.jesi.backpack.exceptions :as ex]
[io.jesi.backpack.macros :refer [catch->identity]]
[io.jesi.backpack.miscellaneous :refer [env-specific]]))
[io.jesi.backpack.miscellaneous :refer [env-specific cljs-env?]]))

(defn closed?
"returns true if the channel is nil or closed"
Expand Down Expand Up @@ -95,16 +94,19 @@
evaluation and should indicate whether to retry
(if it returns true) or not (returns false)"
[{:keys [retries delay should-retry-fn]
:or {retries 5, delay 1, should-retry-fn ex/exception?}}
:or {retries 5, delay 1, should-retry-fn `ex/exception?}}
& body]
(let [go-loop* (env-specific &env 'clojure.core.async/go-loop)
<!* (env-specific &env 'clojure.core.async/<!)]
<!* (env-specific &env 'clojure.core.async/<!)
timeout (env-specific &env 'clojure.core.async/timeout)
delay (* delay 1000)]
`(~go-loop* [retries# ~retries]
(let [res# (catch->identity ~@body)]
(if (and (~should-retry-fn res#)
(pos? retries#))
(do
(~<!* (async/timeout (* ~delay 1000)))
(when (pos? ~delay)
(~<!* (~timeout ~delay)))
(recur (dec retries#)))
res#)))))

Expand Down
26 changes: 20 additions & 6 deletions src/io/jesi/backpack/miscellaneous.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,28 @@
[named]
(some? (namespace named)))

;TODO support other runtimes
(defn- runtime [env]
(cond
(cljs-env? env) :cljs
:else :default))

(defn- ->cljs [sym]
(let [ns (namespace sym)]
(if (and (string/starts-with? ns "clojure.")
(not= "clojure.core" ns))
(symbol
(str "cljs" (subs ns (string/index-of ns \.)))
(name sym))
sym)))

(defn env-specific
"Takes a macro &env and a namespaced symbol, returning the environment specific symbol"
[env sym]
{:pre [(symbol? sym)
(namespaced? sym)]}
(let [ns (namespace sym)
;TODO support other runtimes
ns (if (cljs-env? env)
(str "cljs" (subs ns (string/index-of ns \.)))
ns)]
(symbol ns (name sym))))
(condp = (runtime env)
:cljs (->cljs sym)
:default sym))

;TODO create a macro that take a form and can transform it to the required runtime e.g. cljs ns rename, cljs catch clause
76 changes: 75 additions & 1 deletion test/io/jesi/backpack/async_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
(:require
[clojure.core.async :as core-async]
[clojure.test :refer [deftest testing is]]
[com.rpl.specter :as sp]
[io.jesi.backpack.async :as async]
[io.jesi.backpack.macros :refer [shorthand]]
[io.jesi.backpack.test.macros :refer [async-go]]))
[io.jesi.backpack.miscellaneous :refer [env-specific namespaced?]]
[io.jesi.backpack.test.macros :refer [async-go is=]]
[io.jesi.backpack.test.util :refer [is-macro=]]
#?(:clj [io.jesi.backpack.macros :refer [macro?]])))

(deftest closed?-test

Expand Down Expand Up @@ -50,3 +54,73 @@
(core-async/put! channel true))
(is (async/closed? channel))
(is (nil? (async/<? channel)))))))

(defn ex []
(ex-info "Exceptional" {}))

(def ^:const ex-type #?(:clj Exception :cljs js/Error))

(def list-walker (sp/recursive-path [] l (sp/if-path list? (sp/continue-then-stay sp/ALL l))))

(defn transform-to-env [env quoted-form]
(sp/transform [list-walker sp/FIRST symbol? namespaced?] (partial env-specific env) quoted-form))

(deftest go-retry-test

(testing "go-retry"

#?(:clj (testing "is a macro"
(is (macro? `async/go-retry))))

(testing "expands"
(let [expected '(clojure.core.async/go-loop [retries# 5]
(clojure.core/let [res# (io.jesi.backpack.macros/catch->identity "foo")]
(if (clojure.core/and
(io.jesi.backpack.exceptions/exception? res#)
(clojure.core/pos? retries#))
(do
(clojure.core/when (clojure.core/pos? 1000)
(clojure.core.async/<! (clojure.core.async/timeout 1000)))
(recur (clojure.core/dec retries#)))
res#)))
actual (macroexpand-1 '(io.jesi.backpack.async/go-retry {} "foo"))]
#?(:clj (is-macro= expected actual)
:cljs (is-macro= (transform-to-env {:ns true} expected) actual))))

(testing "is a go block"
(let [value "The heart of a shrimp is located in its head"]
(async-go
(is= value (async/<? (async/go-retry {} value)))

(testing "that bubbles exceptions"
(is (thrown? ex-type (async/<? (async/go-retry
{:retries 1
:delay 0}
(throw (ex)))))))

(testing "that retries based on"

(testing "should-retry-fn"
(is= 4 (let [times (atom 0)]
(async/<? (async/go-retry
{:should-retry-fn (fn [res] (= 0 res))
:retries 3
:delay 0}
(swap! times inc)
0))
@times)))

(testing "retries value"
(let [times (atom 0)]
(is (thrown? ex-type (async/<? (async/go-retry
{:delay 0}
(swap! times inc)
(throw (ex))))))
(is (= 6 @times)))
(let [times (atom 0)]
(is= value (async/<? (async/go-retry
{:delay 0}
(if (< (swap! times inc) 3)
(throw (ex))
value))))
(is= 3 @times)))))))))
14 changes: 13 additions & 1 deletion test/io/jesi/backpack/macros_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[clojure.string :as string]
[clojure.test :refer [deftest testing is use-fixtures]]
[io.jesi.backpack :as bp]
[io.jesi.backpack.macros :refer [try* catch->nil fn1 when-let shorthand condf defconsts when-debug]]
[io.jesi.backpack.macros :refer [try* catch->nil fn1 when-let shorthand condf defconsts when-debug catch->identity]]
[io.jesi.backpack.test.macros :refer [is=]]
[io.jesi.backpack.test.util :refer [is-macro=]])
#?(:clj
Expand Down Expand Up @@ -192,3 +192,15 @@
(throw (ex-info "Unexpected exception" {})))
(set-debug true)
(is= 1 (when-debug 1)))))))

(deftest catch->identity-test

(testing "catch->identity"

#?(:clj (testing "is a macro"
(bp/macro? `catch->identity)))

(testing "returns caught exception"
(is= 1 (catch->identity 1))
(let [ex (ex-info "Elephants are the only animal that can't jump" {:elephant {:sad? true}})]
(is= ex (catch->identity (throw ex)))))))
30 changes: 26 additions & 4 deletions test/io/jesi/backpack/test/macros_test.cljc
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
(ns io.jesi.backpack.test.macros-test
(:require
[clojure.test :refer [deftest testing is]]
[io.jesi.backpack.test.macros]
[io.jesi.backpack.async :as async]
[io.jesi.backpack.test.macros :refer [async-go is=]]
[io.jesi.backpack.test.util :refer [is-macro=]]
#?(:clj [io.jesi.backpack.macros :refer [macro?]])))

(deftest async-go-test

(testing "async-go")

#?(:clj (testing "is a macro"
(is (macro? `io.jesi.backpack.test.macros/async-go))))
(is (macro? `async-go))))

(testing "expands to a `cljs.test/async` `go` block"
(testing "expands "
#?(:clj (is-macro= '(clojure.core.async/<!!
(io.jesi.backpack.async/go
(is true)))
Expand All @@ -22,4 +24,24 @@
(is true)
(finally
(done)))))
(macroexpand-1 '(io.jesi.backpack.test.macros/async-go (is true)))))))
(macroexpand-1 '(io.jesi.backpack.test.macros/async-go (is true))))))

(testing "is a `cljs.test/async` `go` block"
(async-go
(is= 1 (async/<? (async/go-try 1))))))

(deftest is=-test

(testing "is="

#?(:clj (testing "is a macro"
(is (macro? `is=))))

(testing "expands"
(is-macro= #?(:clj '(clojure.test/is (clojure.core/= 1 2 3))
:cljs '(cljs.test/is (clojure.core/= 1 2 3)))
(macroexpand-1 '(io.jesi.backpack.test.macros/is= 1 2 3))))

(testing "is the same as (is (="
(is (= (is (= 1 1))
(is= 1 1))))))

0 comments on commit 27cda43

Please sign in to comment.