-
Notifications
You must be signed in to change notification settings - Fork 0
/
catch_errors.clj
70 lines (62 loc) · 2.41 KB
/
catch_errors.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
;; # Transducer Error Handling
(ns danger-mouse.catch-errors)
(defn process-error
[error input]
{:error-msg (ex-message error)
:error error
:input input})
(def catch-errors
"Transducer to catch errors, capture additional info, and cache them as
DM errors in a side channel that will be returned at the end of the reduction."
(fn [rf]
(let [errors (volatile! [])]
(fn
([] (try (rf)
(catch Exception e
{:result nil
:errors (conj @errors (process-error e nil))})))
([result] (try {:result (rf result)
:errors @errors}
(catch Exception e
{:result result
:errors (conj @errors (process-error e result))})))
([result input] (try (rf result input)
(catch Exception e
(vswap! errors conj (process-error e input))
result)))))))
(defn errors-coll?
[coll]
(and (map? coll) (= (set (keys coll)) #{:result :errors})))
(defn catch-errors->
"Helper function to separate out results from errors in a collection.
Collection is first."
[coll & args]
(let [start (if (errors-coll? coll) (:result coll) coll)
{new-result :result new-errors :errors}
(transduce (apply comp catch-errors args) conj [] start)]
{:result new-result
:errors (into (or (:errors coll) []) new-errors)}))
(defn catch-errors->>
"Helper function to separate out results from errors in a collection.
Collection is last."
[& args-and-coll]
(let [coll (last args-and-coll)
args (drop-last args-and-coll)]
(apply catch-errors-> coll args)))
(defn transduce->
"Helper function to separate out results from errors after applying
a transducer. Collection is first."
[coll xform initial & args]
(let [start (if (errors-coll? coll) (:result coll) coll)
{new-result :result
new-errors :errors}
(transduce (apply comp catch-errors args) xform initial start)]
{:result new-result
:errors (into (or (:errors coll) []) new-errors)}))
(defn transduce->>
"Helper function to separate out results from errors after applying
a transducer. Collection is last."
[xform initial & args-and-coll]
(let [coll (last args-and-coll)
args (drop-last args-and-coll)]
(apply transduce-> coll xform initial args)))