Fix concurrency error where an unsubscription can come in before the subscription is finished causing views to get stuck in the system.

This commit is contained in:
Alexander Hudek 2015-08-10 16:54:37 -04:00
parent ced5a7abd0
commit bff7c9eb5f
2 changed files with 21 additions and 12 deletions

View file

@ -1,4 +1,4 @@
(defproject views "1.4.2" (defproject views "1.4.3"
:description "A view to the past helps navigate the future." :description "A view to the past helps navigate the future."
:url "https://github.com/kirasystems/views" :url "https://github.com/kirasystems/views"

View file

@ -40,23 +40,32 @@
(def refresh-queue (ArrayBlockingQueue. refresh-queue-size)) (def refresh-queue (ArrayBlockingQueue. refresh-queue-size))
(defn subscribe-view! (defn subscribe-view!
[view-system view-sig subscriber-key data-hash] [view-system view-sig subscriber-key]
(-> view-system (-> view-system
(update-in [:subscribed subscriber-key] (fnil conj #{}) view-sig) (update-in [:subscribed subscriber-key] (fnil conj #{}) view-sig)
(update-in [:subscribers view-sig] (fnil conj #{}) subscriber-key) (update-in [:subscribers view-sig] (fnil conj #{}) subscriber-key)))
(update-in [:hashes view-sig] #(or % data-hash)))) ;; see note #1
(defn update-hash!
[view-system view-sig data-hash]
(update-in view-system [:hashes view-sig] #(or % data-hash))) ;; see note #1 in NOTES.md
(defn subscribe! (defn subscribe!
[view-system namespace view-id parameters subscriber-key] [view-system namespace view-id parameters subscriber-key]
(when-let [view (get-in @view-system [:views view-id])] (when-let [view (get-in @view-system [:views view-id])]
(future (let [view-sig [namespace view-id parameters]]
(try (swap! view-system subscribe-view! view-sig subscriber-key)
(let [vdata (data view namespace parameters)] (future
(swap! view-system subscribe-view! [namespace view-id parameters] subscriber-key (hash vdata)) (try
((get @view-system :send-fn) subscriber-key [[view-id parameters] vdata])) (let [vdata (data view namespace parameters)
(catch Exception e data-hash (hash vdata)]
(error "error subscribing:" namespace view-id parameters ;; Check to make sure that we are still subscribed. It's possible that
"e:" e "msg:" (.getMessage e))))))) ;; an unsubscription event came in while computing the view.
(when (get-in @view-system [:subscribed subscriber-key view-sig])
(update-hash! view-system view-sig data-hash)
((get @view-system :send-fn) subscriber-key [[view-id parameters] vdata])))
(catch Exception e
(error "error subscribing:" namespace view-id parameters
"e:" e "msg:" (.getMessage e))))))))
(defn remove-from-subscribers (defn remove-from-subscribers
[view-system view-sig subscriber-key] [view-system view-sig subscriber-key]