Support for in-memory, thread-blocking retrying. | (ns metabase.util.retry (:require [metabase.config :as config] [metabase.models.setting :refer [defsetting]] [metabase.util.i18n :refer [deferred-tru]]) (:import (io.github.resilience4j.core IntervalFunction) (io.github.resilience4j.retry Retry RetryConfig) (java.util.function Predicate))) |
(set! *warn-on-reflection* true) | |
(defsetting retry-max-attempts (deferred-tru "The maximum number of attempts for an event.") :type :integer :default (if config/is-dev? 1 7)) | |
(defsetting retry-initial-interval (deferred-tru "The initial retry delay in milliseconds.") :type :integer :default 500) | |
(defsetting retry-multiplier (deferred-tru "The delay multiplier between attempts.") :type :double :default 2.0) | |
(defsetting retry-randomization-factor (deferred-tru "The randomization factor of the retry delay.") :type :double :default 0.1) | |
(defsetting retry-max-interval-millis (deferred-tru "The maximum delay between attempts.") :type :integer :default 30000) | |
Returns a map with the default retry configuration. | (defn retry-configuration [] {:max-attempts (retry-max-attempts) :initial-interval-millis (retry-initial-interval) :multiplier (retry-multiplier) :randomization-factor (retry-randomization-factor) :max-interval-millis (retry-max-interval-millis)}) |
(defn- make-predicate [f] (reify Predicate (test [_ x] (f x)))) | |
Returns a randomized exponential backoff retry named | (defn random-exponential-backoff-retry ^Retry [^String retry-name {:keys [^long max-attempts ^long initial-interval-millis ^double multiplier ^double randomization-factor ^long max-interval-millis retry-on-result-pred retry-on-exception-pred]}] (let [interval-fn (IntervalFunction/ofExponentialRandomBackoff initial-interval-millis multiplier randomization-factor max-interval-millis) base-config (-> (RetryConfig/custom) (.maxAttempts max-attempts) (.intervalFunction interval-fn)) retry-config (cond-> base-config retry-on-result-pred (.retryOnResult (make-predicate retry-on-result-pred)) retry-on-exception-pred (.retryOnException (make-predicate retry-on-exception-pred)))] (Retry/of retry-name (.build retry-config)))) |
Returns a function accepting the same arguments as | (defn decorate ([f] (decorate f (random-exponential-backoff-retry (str (random-uuid)) (retry-configuration)))) ([f ^Retry retry] (fn [& args] (let [callable (reify Callable (call [_] (apply f args)))] (.call (Retry/decorateCallable retry callable)))))) |
Make a retrying function from (let [retrier (retry/make retry-config)] (retrier f)) | (defn make [retry-config] (fn [f] ((decorate f (random-exponential-backoff-retry (str (random-uuid)) retry-config))))) |