Skip to content
All your fails are belong to us
Clojure
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src/clj/qbits
README.md
project.clj

README.md

checkmate

A minimalist/extensible lib to handle failures and retries in a gracefull way.

I wanted a few things:

  • Pluggable retry strategies
  • Extreme simplicity
  • Composable
  • Not an avalanche of dynamic vars
  • Pluggable reporting via success/error/failure callbacks

Documentation

Right now it has 3 default RetryStrategies implementations (it's a protocol):

  • delay-runner
  • max-runner
  • delay-runner-ch

each run takes a runner instance and options, which can be

  • :success : by default identity - function called on successfull return
  • :error: by default noop - function called on intermediary error
  • :failure: by default #(throw %) - function called when the run failed

We also supply logging-callbacks that does the same as default-callbacks but logs everything as a tuple of [state, return-or-error].

Enough words, code:

(use 'qbits.checkmate)

;; the default
;; after 10 failed tries without pause it'll retrow last error
(run max-runner #(do something that might fail))

;; in fact this translates to

(run max-runner
     #(do something that might fail)
     {:max 10 ;; try max 10 times
      :success (fn [ret] ret) ;; just return value if ok
      :failure #(throw %) ;; throw on failure after 10 tries
      :error identity}) ;; do nothing in intermediate failures

This is quite simple, unobtrusive, you can add metrics/reporting easily on top of that.

The other strategy takes a seq of delays:

(run delay-runner {:delays (take 50 (exponential-backoff 100))})
(run delay-runner {:delays (take 20 (constant-backoff 100))}) ;; try every 100ms
(run delay-runner {:delays (sane-backoff)})

;; etc

Delays must just be a (potentially infinite) lazy seq of ms, super easy to generate manipulate.

The 3 shown before are just:

(defn constant-backoff [ms]
  (repeat ms))

(defn exponential-backoff [x]
  (iterate #(* Math/E %) x))

(defn sane-backoff [x]
  (lazy-cat
   (repeat x 100)
   (repeat x 500)
   (repeat x 1500)
   (repeat x 15000)
   (repeat x 60000)))

There's an equivalent of delay-runner but that runs in a async/go context, delay-runner-ch, so timeouts are a bit cheaper, just make sure your task is non blocking if you don't want to starve the core.async threadpool. The arguments are identical otherwise.

The whole lib is under 100 lines, easy to understand, modify, extend.

Installation

checkmate is available on Clojars.

Clojars Project

License

Copyright © 2016 Max Penet

Distributed under the Eclipse Public License, the same as Clojure.

You can’t perform that action at this time.