-
Notifications
You must be signed in to change notification settings - Fork 1
/
retry.cljc
60 lines (48 loc) · 1.53 KB
/
retry.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(ns promisespromises.promise.retry
(:require
[promesa.core :as pr]
[promisespromises.promise :as prpr]
[promisespromises.error :as err]
[taoensso.timbre :refer [warn]]))
(defn retry-n*
"execute a fn repeatedly until it succeeds
- f - a 1-args function of try-count, yielding a promise
- max-retries - maximum number of times to re-try f before
giving up (if 0 then f will be invoked just once)
- delay-ms - delay between invocations of f"
[f log-description max-retries delay-ms]
#_{:clj-kondo/ignore [:loop-without-recur]}
(pr/loop [n 0]
(prpr/handle-always
(do
(when (> n 0)
(warn "retrying promise:" n log-description))
(f n))
(fn [r e]
(if (some? e)
(if (< n max-retries)
(pr/chain
(pr/timeout
(pr/deferred)
delay-ms
::timeout)
(fn [_]
(pr/recur (inc n))))
(err/wrap-uncaught e))
r)))))
(defn retry-n
[f log-description max-retries delay-ms]
(pr/let [r (retry-n* f log-description max-retries delay-ms)]
(err/unwrap r)))
(defn retry
"execute a fn repeatedly until it succeeds
- f - a 0-args function, yielding a promise
- max-retries - maximum number of times to re-try f before
giving up (if 0 then f will be invoked just once)
- delay-ms - delay between invocations of f"
[f log-description max-retries delay-ms]
(retry-n
(fn [_n] (f))
log-description
max-retries
delay-ms))