Last active
August 8, 2019 17:25
-
-
Save jgrodziski/b0cfd4cd943bc3d000f5bf7eaa39a56f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns promesa-retry | |
(:require | |
["util" :refer [format]] | |
[promesa.core :as p :refer [reject! resolve!] :refer-macros [alet await]] | |
[promesa.async-cljs :refer-macros [async]] | |
[cljs.test :as t :include-macros true])) | |
(defn backoff-duration [retries-count interval] | |
(+ (* interval retries-count) (rand-int interval))) | |
(defn- internal-retry | |
[p f retries-left retries-count interval] | |
(-> (f) | |
(p/catch (fn [err] | |
(js/console.error (format "Catch failure before retrying (%s retried left): %s" retries-left (.-message err))) | |
(if (= 0 retries-left) | |
(p/reject! p err) | |
(let [d (backoff-duration retries-count interval)] | |
(js/console.log (format "Will wait %s ms before retrying (%s retries left, tried %s times)" d retries-left retries-count)) | |
(-> (p/delay d "Retry msg ") | |
(p/then (fn [msg] | |
(internal-retry p f (dec retries-left) (inc retries-count) interval)))))))) | |
(p/catch (fn [err]));this catch is needed to get the promise returned by the the previous catch in case of a retry, we catch the error cause and do nothing with it | |
(p/then (fn [return] | |
(p/resolve! p return)))) | |
p) | |
(defn retry | |
([f retries-left] | |
(retry f retries-left 1000)) | |
([f retries-left interval] | |
(internal-retry (p/promise) f retries-left 1 interval))) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Test ;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
(def counter (atom 0)) | |
(defn dummy-function [] | |
(async | |
(if (< @counter 6) | |
(do (println "Dummy function failed!") | |
(swap! counter inc) | |
(throw (ex-info "it failed !" {:counter @counter}))) | |
(println "yo it works!")))) | |
(t/deftest retry-test-success-in-the-end | |
(reset! counter 0) | |
(t/async done | |
(-> (retry dummy-function 15 10) | |
(p/catch (fn [err] | |
(t/is err) | |
(done))) | |
(p/then (fn [] | |
(js/console.log (format "Done retrying, success in the end")) | |
(done)))))) | |
(t/deftest retry-test-failure-in-the-end | |
(reset! counter 0) | |
(t/async done | |
(-> (retry dummy-function 3 10) | |
(p/catch (fn [err] | |
(js/console.log "Done retrying, error in the end") | |
(t/is err) | |
(done))) | |
(p/then (fn [] | |
(js/console.log "Done retrying successfully") | |
(done))) | |
))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment