Skip to content
Exception net
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
test/qbits/ex/test
CHANGELOG.md
README.md
deps.edn
project.clj

README.md

ex

cljdoc badge

An exception library, drop in replacement for try/catch/finally, that adds support for ex-info/ex-data with a custom (clojure) hierarchy that allows to express exceptions relations.

So we have qbits.ex/try+, which supports vanilla catch/finally clauses. If you specify a catch-data clause with a keyword as first argument things get interesting. We assume you always put a :type key in the ex-info you want to use with this, and will match its value to the value of the key in the catch-data clause.

Essentially catch-data takes this form:

(catch-data :something m
   ;; where m is a binding to the ex-data (you can destructure at that level as well)
   )

So you can do things like that.

(require '[qbits.ex :as ex])

(ex/try+

  (throw (ex-info "Argh" {:type ::bar :foo "a foo"}))

  (catch-data ::foo data
    (prn :got-ex-data data))

  (catch-data ::bar {:as data :keys [foo]}
    ;; in that case it would hit this one
    (prn :got-ex-data-again foo))

  (catch ExceptionInfo e
   ;; this would match an ex-info that didn't get a hit with catch-ex-info)

  (catch Exception e (prn :boring))

  (finally (prn :boring-too)))

But there's a twist.

I thought leveraging a clojure hierarchy could make sense in that context too, so you can essentially create exceptions hierachies without having to mess with Java classes directly and in a clojuresque" way.

;; so bar is a foo

(ex/derive ::bar ::foo)

(ex/try+
  (throw (ex-info "I am a bar" {:type ::bar})
  (catch-data ::foo d
    (prn "got a foo with data" d)
    (prn "Original exception instance is " (-> d meta ::ex/exception))))

You can also get the full exception instance via the metadata on the ex-data we extract, it's under the :qbits.ex/exception key.

Some real life examples of usage for this:

  • make some exceptions end-user exposable in http responses via an error middleware in a declarative way .

  • skip sentry logging for some kind of exceptions (or the inverse)

  • make an exception hierachy for our query language type of errors for specialized reporting per "type"

Other than that it's largely inspired by catch-data, the implementation is slightly different, we dont catch Throwable, we instead generate a catch clause on clj ex-info and generate a cond that tries to match ex-data with the :type key using isa? with our hierarchy, which arguably is closer to I would write by hand in that case.

Installation

ex is available on Clojars.

Add this to your dependencies:

Clojars Project

or you can just grab it via deps.edn directly

License

Copyright © 2018 Max Penet

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

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.