From 50b54683c47486c10b417aff0a18dd57481ff885 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 29 Nov 2019 12:54:24 +0100 Subject: [PATCH] :sparkles: Properly handle page history. --- backend/src/uxbox/fixtures.clj | 40 +++++++++---- backend/src/uxbox/services/core.clj | 6 +- backend/src/uxbox/services/kvstore.clj | 12 +--- backend/src/uxbox/services/pages.clj | 78 +++++++++++++++----------- 4 files changed, 80 insertions(+), 56 deletions(-) diff --git a/backend/src/uxbox/fixtures.clj b/backend/src/uxbox/fixtures.clj index ffbf25e4f..7cf776b3d 100644 --- a/backend/src/uxbox/fixtures.clj +++ b/backend/src/uxbox/fixtures.clj @@ -59,9 +59,15 @@ ;; --- Pages creation (def create-page-sql - "insert into pages (id, user_id, project_id, name, ordering, data, metadata) - values ($1, $2, $3, $4, $5, $6, $7) - returning *;") + "insert into pages (id, user_id, project_id, name, + version, ordering, data, metadata) + values ($1, $2, $3, $4, $5, $6, $7, $8) + returning id;") + +(def create-page-history-sql + "insert into pages_history (page_id, user_id, version, data, metadata) + values ($1, $2, $3, $4, $5) + returning id;") (defn create-page [conn [pjid paid uid]] @@ -73,15 +79,25 @@ :x1 200 :y1 200 :x2 1224 - :y2 968}]}] - (db/query-one conn [create-page-sql - (mk-uuid "page" pjid paid uid) - (mk-uuid "user" uid) - (mk-uuid "project" pjid uid) - (str "page " paid) - paid - (blob/encode data) - (blob/encode {})]))) + :y2 968}]} + data (blob/encode data) + mdata (blob/encode {})] + (p/do! + (db/query-one conn [create-page-sql + (mk-uuid "page" pjid paid uid) + (mk-uuid "user" uid) + (mk-uuid "project" pjid uid) + (str "page " paid) + 0 + paid + data + mdata]) + (db/query-one conn [create-page-history-sql + (mk-uuid "page" pjid paid uid) + (mk-uuid "user" uid) + 0 + data + mdata])))) (def num-users 5) diff --git a/backend/src/uxbox/services/core.clj b/backend/src/uxbox/services/core.clj index 3da03ca42..81dafe6c9 100644 --- a/backend/src/uxbox/services/core.clj +++ b/backend/src/uxbox/services/core.clj @@ -19,9 +19,9 @@ java.util.Map$Entry java.util.HashMap)) -(def context-interceptor - {:enter (fn [data] - (update data :request assoc ::ctx (vc/get-or-create-context system)))}) +;; (def context-interceptor +;; {:enter (fn [data] +;; (update data :request assoc ::ctx (vc/get-or-create-context system)))}) (def logging-interceptor {:enter (fn [data] diff --git a/backend/src/uxbox/services/kvstore.clj b/backend/src/uxbox/services/kvstore.clj index ffeb9a8b9..7fee6d330 100644 --- a/backend/src/uxbox/services/kvstore.clj +++ b/backend/src/uxbox/services/kvstore.clj @@ -31,9 +31,7 @@ (s/def ::upsert-kvstore (s/keys :req-un [::key ::value ::user])) -(sv/defmutation :upsert-kvstore - {:doc "Update or insert kvstore entry." - :spec ::upsert-kvstore} +(sv/defmutation ::upsert-kvstore [{:keys [key value user] :as params}] (let [sql "insert into kvstore (key, value, user_id) values ($1, $2, $3) @@ -48,9 +46,7 @@ (s/def ::kvstore-entry (s/keys :req-un [::key ::user])) -(sv/defquery :kvstore-entry - {:doc "Retrieve kvstore entry." - :spec ::kvstore-entry} +(sv/defquery ::kvstore-entry [{:keys [key user]}] (let [sql "select kv.* from kvstore as kv @@ -65,9 +61,7 @@ (s/def ::delete-kvstore (s/keys :req-un [::key ::user])) -(sv/defmutation :delete-kvstore - {:doc "Delete kvstore entry." - :spec ::delete-kvstore} +(sv/defmutation ::delete-kvstore [{:keys [user key] :as params}] (let [sql "delete from kvstore where user_id = $2 diff --git a/backend/src/uxbox/services/pages.clj b/backend/src/uxbox/services/pages.clj index d15d99f2c..57705d0e8 100644 --- a/backend/src/uxbox/services/pages.clj +++ b/backend/src/uxbox/services/pages.clj @@ -28,7 +28,6 @@ (s/def ::project-id ::us/uuid) (s/def ::metadata any?) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Queries ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -38,9 +37,7 @@ (s/def ::pages-by-project (s/keys :req-un [::user ::project-id])) -(sv/defquery :pages-by-project - {:doc "List pages by project id." - :spec ::pages-by-project} +(sv/defquery ::pages-by-project [{:keys [user project-id] :as params}] (let [sql "select pg.*, pg.data, @@ -58,9 +55,7 @@ (s/def ::page (s/keys :req-un [::user ::id])) -(sv/defquery :page - {:doc "Retrieve page by id." - :spec ::page} +(sv/defquery ::page [{:keys [user id] :as params}] (let [sql "select pg.*, pg.data, @@ -121,9 +116,7 @@ (s/keys :req-un [::data ::user ::project-id ::name ::metadata] :opt-un [::id])) -(sv/defmutation :create-page - {:doc "Create a new page." - :spec ::create-page} +(sv/defmutation ::create-page [{:keys [id user project-id name data metadata]}] (let [sql "insert into pages (id, user_id, project_id, name, data, metadata) values ($1, $2, $3, $4, $5, $6) returning *" @@ -139,32 +132,55 @@ (s/def ::update-page (s/keys :req-un [::data ::user ::project-id ::name ::data ::metadata ::id])) -(sv/defmutation :update-page - {:doc "Update an existing page." - :spec ::update-page} - [{:keys [id user project-id name data metadata]}] - (let [sql "update pages - set name = $1, - data = $2, - metadata = $3 - where id = $4 - and user_id = $5 - and deleted_at is null - returning *" - data (blob/encode data) - mdata (blob/encode metadata)] - (-> (db/query-one db/pool [sql name data mdata id user]) - (p/then' decode-row)))) +(letfn [(select-for-update [conn id] + (let [sql "select p.id, p.version + from pages as p + where p.id = $1 + and deleted_at is null + for update;"] + (-> (db/query-one conn [sql id]) + (p/then' sv/raise-not-found-if-nil)))) + (update-page [conn {:keys [id name version data metadata user]}] + (let [sql "update pages + set name = $1, + version = $2, + data = $3, + metadata = $4 + where id = $5 + and user_id = $6"] + (-> (db/query-one conn [sql name version data metadata id user]) + (p/then' sv/constantly-nil)))) + + (update-history [conn {:keys [user id version data metadata]}] + (let [sql "insert into pages_history (user_id, page_id, version, data, metadata) + values ($1, $2, $3, $4, $5)"] + (-> (db/query-one conn [sql user id version data metadata]) + (p/then' sv/constantly-nil))))] + + (sv/defmutation ::update-page + [{:keys [id data metadata] :as params}] + (db/with-atomic [conn db/pool] + (-> (select-for-update conn id) + (p/then (fn [{:keys [id version]}] + (let [data (blob/encode data) + mdata (blob/encode metadata) + version (inc version) + params (assoc params + :id id + :version version + :data data + :metadata mdata)] + (p/do! (update-page conn params) + (update-history conn params) + (select-keys params [:id :version]))))))))) ;; --- Mutation: Update Page Metadata (s/def ::update-page-metadata (s/keys :req-un [::user ::project-id ::name ::metadata ::id])) -(sv/defmutation :update-page-metadata - {:doc "Update an existing page." - :spec ::update-page-metadata} +(sv/defmutation ::update-page-metadata [{:keys [id user project-id name metadata]}] (let [sql "update pages set name = $3, @@ -182,9 +198,7 @@ (s/def ::delete-page (s/keys :req-un [::user ::id])) -(sv/defmutation :delete-page - {:doc "Delete existing page." - :spec ::delete-page} +(sv/defmutation ::delete-page [{:keys [id user]}] (let [sql "update pages set deleted_at = clock_timestamp()