-
Notifications
You must be signed in to change notification settings - Fork 9
/
utils.clj
98 lines (84 loc) · 2.51 KB
/
utils.clj
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
(ns goose.utils
(:refer-clojure :exclude [list])
(:require
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.climate.claypoole :as cp]
[taoensso.nippy :as nippy])
(:import
(java.net InetAddress)
(java.time Instant)))
(defn encode [x]
(nippy/freeze x))
(defn decode [o]
(nippy/thaw o))
(defmacro ^:no-doc log-on-exceptions
"Catch any Exception from the body and log it."
[& body]
`(try
~@body
(catch Exception e#
(when-not (= "sleep interrupted" (ex-message e#))
(log/error e# "Exception occurred")))))
(defn epoch-time-ms
"Returns Unix epoch milliseconds for given java.time.Instant.
If no instant is given, returns epoch for current time."
([] (System/currentTimeMillis))
([instant] (.toEpochMilli ^Instant instant)))
(defn- sec->ms [sec]
(* 1000 sec))
(defn ^:no-doc sec+current-epoch-ms
([sec] (+ (sec->ms sec) (epoch-time-ms))))
(defn ^:no-doc sleep
"Sleep for given seconds, multiplied by count.
Sleep duration: (seconds * count) + jitters"
([sec]
(Thread/sleep (sec->ms sec)))
([sec multiplier-count]
;; `Thread/sleep` converts float to long value.
;; For sec=3, multiplier-count=5, it sleeps for
;; [15,000, 16,000) milliseconds.
(Thread/sleep (sec->ms (+ (* sec multiplier-count) (rand))))))
(defmacro ^:no-doc while-pool
[pool & body]
`(while (not (cp/shutdown? ~pool))
~@body))
(defn ^:no-doc require-resolve
[fn-sym]
(-> fn-sym
(str)
(str/split #"/")
(first)
(symbol)
(require))
(resolve fn-sym))
(defn ^:no-doc arities
[fn-sym]
(->> fn-sym
(resolve)
(meta)
(:arglists)
(map count)))
(defn ^:no-doc hostname []
(.getHostName (InetAddress/getLocalHost)))
(defn ^:no-doc random-element
"Randomly select an element from a list & return it."
[list]
(if (zero? (count list))
(throw (ex-info "List is empty." {:empty-list list}))
(nth list (rand-int (count list)))))
(defn with-retry* [retry-count retry-delay-ms fn-to-retry]
(let [res (try
(fn-to-retry)
(catch Exception e
(if (< 0 retry-count)
e
(throw e))))]
(if (instance? Throwable res)
(do
(log/warnf "Exception caught: %s. Retrying in %dms." res retry-delay-ms)
(Thread/sleep retry-delay-ms)
(recur (dec retry-count) retry-delay-ms fn-to-retry))
res)))
(defmacro with-retry [{:keys [count retry-delay-ms]} & body]
`(with-retry* ~count ~retry-delay-ms (fn [] ~@body)))