Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Last active December 20, 2019 04:31
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save olivergeorge/0eeac90c44a2019afa4508504462e002 to your computer and use it in GitHub Desktop.
Save olivergeorge/0eeac90c44a2019afa4508504462e002 to your computer and use it in GitHub Desktop.

Introduction

Stuart talking about them as part of the Day of Datomic videos:

https://youtu.be/ZP-E2IgqKfA?t=2412

Simple data structure

Simple data structure for anomalies.

(s/def ::category #{::unavailable
                    ::interrupted
                    ::incorrect
                    ::forbidden
                    ::unsupported
                    ::not-found
                    ::conflict
                    ::fault
                    ::busy})

(s/def ::message string?)

(s/def ::anomaly (s/keys :req [::category]
                         :opt [::message]))

Ref https://github.com/cognitect-labs/anomalies

Fixed set of anomaly categories

Part of the secret sauce is that there is a finite set so you can confidently cover all cases in your code.

Table of categories and what they mean.

category retry fix song
:unavailable yes make sure callee healthy Out of Touch
:interrupted yes stop interrupting It Doesn't Matter Anymore
:incorrect no fix caller bug You'll Never Learn
:forbidden no fix caller creds I Can't Go For That
:unsupported no fix caller verb Your Imagination
:not-found no fix caller noun She's Gone
:conflict no coordinate with callee Give It Up
:fault no fix callee bug Falling
:busy yes backoff and retry Wait For Me

Ref https://github.com/cognitect-labs/anomalies

Utilities

Useful helpers for creating anomalies and testing for them...

(def ^:dynamic *default-category* ::fault)

(defn valid-category?
  "Checks if given category exists in the list of categories"
  {:added "0.1.0"}
  [cat]
  (s/valid? ::category cat))

(defn anomaly?
  "Checks if given value is anomaly"
  {:added "0.1.0"}
  [x]
  (s/valid? ::anomaly x))

(defn anomaly
  "Creates new anomaly with given category(defaults to ::fault) message(optional) and data(optional)"
  {:added "0.1.0"}
  ([] (anomaly *default-category* nil nil))
  ([cat-msg-data]
   (cond
     (valid-category? cat-msg-data) (anomaly cat-msg-data nil nil)
     (string? cat-msg-data) (anomaly *default-category* cat-msg-data nil)
     :else (anomaly *default-category* nil cat-msg-data)))
  ([cat-msg msg-data]
   (cond
     (and (valid-category? cat-msg) (string? msg-data)) (anomaly cat-msg msg-data nil)
     (valid-category? cat-msg) (anomaly cat-msg nil msg-data)
     (string? cat-msg) (anomaly *default-category* cat-msg msg-data)
     :else (anomaly *default-category* cat-msg msg-data)))
  ([cat msg data]
   {:pre [(valid-category? cat)
          (or (nil? msg) (string? msg))]}
   (cond-> {::category cat}
     (some? msg) (assoc ::message msg)
     (some? data) (assoc ::data data))))

(def busy (partial anomaly ::busy))
(def busy? #(= (::category %) ::busy))
(def conflict (partial anomaly ::conflict))
(def conflict? #(= (::category %) ::conflict))
(def fault (partial anomaly ::fault))
(def fault? #(= (::category %) ::fault))
(def forbidden (partial anomaly ::forbidden))
(def forbidden? #(= (::category %) ::forbidden))
(def incorrect (partial anomaly ::incorrect))
(def incorrect? #(= (::category %) ::incorrect))
(def interrupted (partial anomaly ::interrupted))
(def interrupted? #(= (::category %) ::interrupted))
(def not-found (partial anomaly ::not-found))
(def not-found? #(= (::category %) ::not-found))
(def unavailable (partial anomaly ::unavailable))
(def unavailable? #(= (::category %) ::unavailable))
(def unsupported (partial anomaly ::unsupported))
(def unsupported? #(= (::category %) ::unsupported))

(def message ::message)
(def data ::data)
(def category ::category)

Ref https://github.com/fmnoise/anomalies-tools

Translating HTTP status codes

Useful helpers for translating HTTP status codes into anomalies

(def status-codes->anomalies
  {403 ::forbidden
   404 ::not-found
   503 ::busy
   504 ::unavailable})

(defn status-code->anomaly [code]
  (or (get status-codes->anomalies code)
      (if (<= 400 code 499)
        ::incorrect
        ::fault)))

Ref https://github.com/cognitect-labs/aws-api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment