Allow serialization errors through internal error handling.
This commit is contained in:
parent
e67aa2508a
commit
d88471409e
|
@ -1,4 +1,4 @@
|
|||
(defproject views "0.4.3"
|
||||
(defproject views "0.4.4"
|
||||
:description "You underestimate the power of the SQL side"
|
||||
|
||||
:url "https://github.com/diligenceengine/views"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
(ns views.db.deltas
|
||||
(:import (java.sql SQLException))
|
||||
(:require
|
||||
[clojure.string :refer [split]]
|
||||
[clojure.java.jdbc :as j]
|
||||
|
@ -8,7 +9,7 @@
|
|||
[views.db.load :as vdbl]
|
||||
[views.db.checks :as vc]
|
||||
[views.db.honeysql :as vh]
|
||||
[views.db.util :refer [safe-map log-exception]]))
|
||||
[views.db.util :refer [safe-map log-exception serialization-error?]]))
|
||||
|
||||
;;
|
||||
;; Terminology and data structures used throughout this code
|
||||
|
@ -218,9 +219,10 @@
|
|||
(try
|
||||
(let [refresh-set (get (vdbl/initial-view db view-sig templates view) view-sig)]
|
||||
(update-in d [view-sig] (update-deltas-with-refresh-set refresh-set)))
|
||||
(catch Exception e ;; ignore any failed view deltas
|
||||
(log-exception e)
|
||||
d)))
|
||||
;; allow serialization errors
|
||||
(catch SQLException e (if (serialization-error? e) (throw e) d))
|
||||
;; ignore any failed view deltas
|
||||
(catch Exception e (log-exception e) d)))
|
||||
deltas
|
||||
refresh-only-views))
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
;; java.sql.SQLException: ERROR: could not serialize access due to concurrent update
|
||||
;;
|
||||
(defn get-nested-exceptions*
|
||||
[exceptions e]
|
||||
[exceptions ^SQLException e]
|
||||
(if-let [next-e (.getNextException e)]
|
||||
(recur (conj exceptions next-e) next-e)
|
||||
exceptions))
|
||||
|
@ -19,6 +19,11 @@
|
|||
[e]
|
||||
(get-nested-exceptions* [e] e))
|
||||
|
||||
(defn serialization-error?
|
||||
"True if e is a serialization error."
|
||||
[^SQLException e]
|
||||
(boolean (some #(= (.getSQLState ^SQLException %) "40001") (get-nested-exceptions e))))
|
||||
|
||||
;; TODO: update to avoid stack overflow.
|
||||
(defn retry-on-transaction-failure
|
||||
"Retry a function whenever we receive a transaction failure."
|
||||
|
@ -31,7 +36,7 @@
|
|||
(debug "Exception message: " (.getMessage e))
|
||||
|
||||
;; (debug "stack trace message: " (.printStackTrace e))
|
||||
(if (some #(= (.getSQLState %) "40001") (get-nested-exceptions e))
|
||||
(if (serialization-error? e)
|
||||
(retry-on-transaction-failure transaction-fn) ;; try it again
|
||||
(throw e))))) ;; otherwise rethrow
|
||||
|
||||
|
@ -42,7 +47,7 @@
|
|||
(retry-on-transaction-failure tfn#)))
|
||||
|
||||
(defn log-exception
|
||||
[e]
|
||||
[^Exception e]
|
||||
(error "views internal"
|
||||
(str
|
||||
"e: " e
|
||||
|
@ -50,6 +55,11 @@
|
|||
" trace: " (with-out-str (print-stack-trace e)))))
|
||||
|
||||
(defn safe-map
|
||||
"A non-lazy map that skips any results that throw exeptions."
|
||||
"A non-lazy map that skips any results that throw exeptions other than SQL
|
||||
serialization errors."
|
||||
[f items]
|
||||
(reduce #(try (conj %1 (f %2)) (catch Exception e %1)) [] items))
|
||||
(reduce #(try (conj %1 (f %2))
|
||||
(catch SQLException e (if (serialization-error? e) (throw e) %1))
|
||||
(catch Exception e %1))
|
||||
[]
|
||||
items))
|
||||
|
|
Loading…
Reference in a new issue