-
Notifications
You must be signed in to change notification settings - Fork 6
/
ratelimiter.clj
71 lines (54 loc) · 2.4 KB
/
ratelimiter.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
(ns resilience.ratelimiter
(:refer-clojure :exclude [name])
(:require [resilience.util :as u])
(:import (java.time Duration)
(io.github.resilience4j.ratelimiter RateLimiterConfig RateLimiterConfig$Builder RateLimiterRegistry RateLimiter)))
(defn ^RateLimiterConfig rate-limiter-config [opts]
(if (empty? opts)
(throw (IllegalArgumentException. "please provide not empty configuration for rate limiter."))
(let [^RateLimiterConfig$Builder config (RateLimiterConfig/custom)]
(when-let [timeout (:timeout-millis opts)]
(.timeoutDuration config (Duration/ofMillis timeout)))
(when-let [limit (:limit-for-period opts)]
(.limitForPeriod config (int limit)))
(when-let [period-millis (:limit-refresh-period-millis opts)]
(.limitRefreshPeriod config (Duration/ofMillis period-millis)))
(.build config))))
(defn ^RateLimiterRegistry registry-with-config [^RateLimiterConfig config]
(RateLimiterRegistry/of config))
(defmacro defregistry [name config]
(let [sym (with-meta (symbol name) {:tag `RateLimiterRegistry})]
`(def ~sym
(let [config# (rate-limiter-config ~config)]
(registry-with-config config#)))))
(defn get-all-rate-limiters [^RateLimiterRegistry registry]
(let [heads (.getAllRateLimiters registry)
iter (.iterator heads)]
(u/lazy-seq-from-iterator iter)))
(defn rate-limiter [^String name config]
(let [^RateLimiterRegistry registry (:registry config)
config (dissoc config :registry)]
(cond
(and registry (not-empty config))
(let [config (rate-limiter-config config)]
(.rateLimiter registry name ^RateLimiterConfig config))
registry
(.rateLimiter registry name)
:else
(let [config (rate-limiter-config config)]
(RateLimiter/of name ^RateLimiterConfig config)))))
;; name configs
;; name registry
;; name registry configs
(defmacro defratelimiter [name config]
(let [sym (with-meta (symbol name) {:tag `RateLimiter})
^String name-in-string (str *ns* "/" name)]
`(def ~sym (rate-limiter ~name-in-string ~config))))
(defn name [^RateLimiter breaker]
(.getName breaker))
(defn config [^RateLimiter breaker]
(.getRateLimiterConfig breaker))
(defn metrics [^RateLimiter breaker]
(let [metric (.getMetrics breaker)]
{:number-of-waiting-threads (.getNumberOfWaitingThreads metric)
:available-permissions (.getAvailablePermissions metric)}))