subscribing stores compiled views

This commit is contained in:
Dave Della Costa 2014-06-06 20:34:51 +09:00
parent e901e70057
commit 3dc546e192
5 changed files with 70 additions and 50 deletions

View file

@ -11,7 +11,7 @@
[clojure.java.jdbc :as j]
[clojure.tools.logging :refer [debug]]
[views.honeysql :as vh]
[views.subscribed-views :refer [get-subscribed-views broadcast-deltas]]))
[views.subscribed-views :refer [subscribed-views broadcast-deltas]]))
(defn get-primary-key
"Get a primary key for a table."
@ -468,7 +468,7 @@
calculate for them and associated with the hash-maps (appropriately
called views-with-deltas)."
[schema db action-map subscribed-views]
(let [subbed-views (get-subscribed-views subscribed-views db)
(let [subbed-views (subscribed-views subscribed-views db)
transaction-fn #(do-view-transaction schema db subbed-views action-map)]
(if-let [deltas (:deltas db)] ;; inside a transaction we just collect deltas and do not retry
(let [{:keys [views-with-deltas result-set]} (transaction-fn)]

View file

@ -1,4 +1,6 @@
(ns views.subscriptions)
(ns views.subscriptions
(:require
[views.db :as vdb]))
;;
;; {[:view-sig 1 "arg2"] {:keys [1 2 3 4 ... ] :view-map {:view ...}}}
@ -18,20 +20,26 @@
(conj view-subs subscriber-key)
#{subscriber-key})))
(defn- add-compiled-view!
[view-sig templates]
(swap! compiled-views #(assoc % view-sig (vdb/view-map (get-in templates [(first view-sig) :fn]) view-sig))))
(defn add-subscription!
([subscriber-key view-sig]
(swap! subscribed-views #(update-in % [view-sig] (add-subscriber-key subscriber-key))))
([subscriber-key view-sig prefix]
(swap! subscribed-views #(update-in % [prefix view-sig] (add-subscriber-key subscriber-key)))))
([subscriber-key view-sig templates]
(swap! subscribed-views #(update-in % [view-sig] (add-subscriber-key subscriber-key)))
(add-compiled-view! view-sig templates))
([subscriber-key view-sig templates prefix]
(swap! subscribed-views #(update-in % [prefix view-sig] (add-subscriber-key subscriber-key)))
(add-compiled-view! view-sig templates)))
(defn add-subscriptions!
([subscriber-key view-sigs]
(add-subscriptions! subscriber-key view-sigs nil))
([subscriber-key view-sigs prefix]
([subscriber-key view-sigs templates]
(add-subscriptions! subscriber-key view-sigs templates nil))
([subscriber-key view-sigs templates prefix]
(doseq [vs view-sigs]
(if prefix
(add-subscription! subscriber-key vs prefix)
(add-subscription! subscriber-key vs)))))
(add-subscription! subscriber-key vs templates prefix)
(add-subscription! subscriber-key vs templates)))))
(defn subscribed-to
([view-sig]
@ -53,9 +61,10 @@
updated (update-in subbed-views path disj subscriber-key)]
(if (seq (get-in updated path))
updated
(if prefix
(update-in updated [prefix] dissoc view-sig)
(dissoc updated view-sig))))))
(do (swap! compiled-views dissoc view-sig) ; remove the compiled view as well
(if prefix
(update-in updated [prefix] dissoc view-sig)
(dissoc updated view-sig)))))))
(defn remove-subscription!
([subscriber-key view-sig]
@ -63,3 +72,7 @@
([subscriber-key view-sig prefix]
(when (subscribed-to? subscriber-key view-sig (if prefix prefix))
(swap! subscribed-views (remove-key-or-view subscriber-key view-sig prefix)))))
(defn compiled-view-for
[view-sig]
(get @compiled-views view-sig))

View file

@ -2,26 +2,12 @@
(:require
[clojure.test :refer [use-fixtures deftest is]]
[honeysql.core :as hsql]
[views.fixtures :as vf :refer [gen-n-users! database-fixtures!]]
[views.fixtures :as vf :refer [gen-n-users! database-fixtures! templates]]
[views.db.core :as vdb]
[clojure.string :refer [upper-case]]))
(use-fixtures :each database-fixtures!)
(defn users-tmpl
[]
(hsql/build :select [:id :name :created_on] :from :users))
(defn user-posts-tmpl
[user_id]
(hsql/build :select [:u.user_id :u.name :p.title :p.body :p.created_on]
:from {:posts :p}
:join [[:users :u][:= :user_id user_id]]))
(def templates
{:users {:fn #'users-tmpl}
:user-posts {:fn #'user-posts-tmpl}})
(defn subscribed-views
[]
{[:users] {:view-map ((get-in templates [:users :fn]))}})

View file

@ -52,3 +52,17 @@
(dotimes [n n]
(user-fixture! (dg/string #(rand-nth (seq "abcdefghijklmnopqrstuwvxyz")))))
(j/query db ["SELECT * FROM users"]))
(defn users-tmpl
[]
(hsql/build :select [:id :name :created_on] :from :users))
(defn user-posts-tmpl
[user_id]
(hsql/build :select [:u.user_id :u.name :p.title :p.body :p.created_on]
:from {:posts :p}
:join [[:users :u][:= :user_id user_id]]))
(def templates
{:users {:fn #'users-tmpl}
:user-posts {:fn #'user-posts-tmpl}})

View file

@ -1,6 +1,7 @@
(ns views.subscriptions-test
(:require
[clojure.test :refer [use-fixtures deftest is]]
[views.fixtures :refer [templates user-posts-tmpl]]
[views.subscriptions :as vs]))
(defn- reset-subscribed-views!
@ -11,49 +12,55 @@
(use-fixtures :each reset-subscribed-views!)
(deftest adds-a-subscription
(let [key 1, view-sig [:view 1]]
(vs/add-subscription! key view-sig)
(let [key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates)
(is (vs/subscribed-to? key view-sig))))
(deftest can-use-prefix
(let [prefix1 1, prefix2 2, key 1, view-sig [:view 1]]
(vs/add-subscription! key view-sig prefix1)
(vs/add-subscription! key view-sig prefix2)
(let [prefix1 1, prefix2 2, key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates prefix1)
(vs/add-subscription! key view-sig templates prefix2)
(is (vs/subscribed-to? key view-sig prefix1))
(is (vs/subscribed-to? key view-sig prefix2))))
(deftest removes-a-subscription
(let [key 1, view-sig [:view 1]]
(vs/add-subscription! key view-sig)
(let [key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates)
(vs/remove-subscription! key view-sig)
(is (not (vs/subscribed-to? key view-sig)))))
(deftest doesnt-fail-or-create-view-entry-when-empty
(vs/remove-subscription! 1 [:view 1])
(vs/remove-subscription! 1 [:user-posts 1])
(is (= {} @vs/subscribed-views)))
(deftest removes-a-subscription-with-prefix
(let [prefix1 1, prefix2 2, key 1, view-sig [:view 1]]
(vs/add-subscription! key view-sig prefix1)
(vs/add-subscription! key view-sig prefix2)
(let [prefix1 1, prefix2 2, key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates prefix1)
(vs/add-subscription! key view-sig templates prefix2)
(vs/remove-subscription! key view-sig prefix1)
(is (not (vs/subscribed-to? key view-sig prefix1)))
(is (vs/subscribed-to? key view-sig prefix2))))
(deftest removes-unsubscribed-to-view-from-subscribed-views
(let [key 1, view-sig [:view 1]]
(vs/add-subscription! key view-sig)
(let [key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates)
(vs/remove-subscription! key view-sig)
(is (= {} @vs/subscribed-views))))
(deftest adds-multiple-views-at-a-time
(let [key 1, view-sigs [[:view 1] [:view 2]]]
(vs/add-subscriptions! key view-sigs)
(let [key 1, view-sigs [[:user-posts 1] [:user-posts 2]]]
(vs/add-subscriptions! key view-sigs templates)
(is (vs/subscribed-to? key (first view-sigs)))
(is (vs/subscribed-to? key (last view-sigs)))))
;; (deftest subscribing-compiles-and-stores-view-maps
;; (let [key 1, view-sig [:view 1]]
;; (vs/add-subscriptions! key view-sigs)
;; (is (vs/subscribed-to? key (first view-sigs)))
;; (is (vs/subscribed-to? key (last view-sigs)))))
(deftest subscribing-compiles-and-stores-view-maps
(let [key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates)
(is (= (:view (vs/compiled-view-for [:user-posts 1]))
(user-posts-tmpl 1)))))
(deftest removing-last-view-sub-removes-compiled-view
(let [key 1, view-sig [:user-posts 1]]
(vs/add-subscription! key view-sig templates)
(vs/remove-subscription! key view-sig)
(is (nil? (vs/compiled-view-for [:user-posts 1])))))