sparkledriver.retry

*retry-fn*

dynamic

retry-backoff

(retry-backoff max-wait try-fn)(retry-backoff max-wait recover-fn try-fn)

Execute try-fn, catching any exception and then retrying with an exponential backoff until a retry pause of max-wait seconds is reached. If recover-fn is supplied, it will be called before each retry with the most recent exception as its only argument. Either returns the result of a successful invocation of try-fn or raises an exception.

If try-fn throws an :unhandled-fatal exception the retry loop will terminate.

Simple example:

  (retry-backoff
    ;; retry at 2,4 and 8 seconds
    8
    ;; return the value of element w/ id "the-id" if successful
    #(find-by-id browser "the-id"))

Add a recovery-fn to the retry, which in this case just logs the exception:

  (retry-backoff
    ;; retry at 2,4,8 and 16 seconds
    16
    ;; "recover-fn" that logs failures between retries
    #(info (str "Trying again after a " (.getMessage %) " exception..."))
    ;; return the value of element w/ id "the-id" if successful
    #(find-by-id browser "the-id"))

with-retry

macro

(with-retry retry-fn & body)

Evaluate body with retry-fn bound to the dynamic variable *retry-fn*. Many Sparkledriver functions automatically wrap themselves in *retry-fn* when it is bound, which allows one to specify a retry policy for those functions within the scope of this macro.

Example:

  (with-browser [browser (make-browser)]
    (fetch! browser "http://clojure.org")  
    (with-retry (partial retry-backoff 16)
      (-> browser
          (find-by-xpath* "//div[@class='clj-intro-message']/p")
          (nth 2)
          text)))
;;=> "I hope you find Clojure's combination of facilities elegant, powerful, practical and fun to use."