0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 08:20:45 -05:00

Reduce contention on file-update using advisory locks and weaker row locking.

This commit is contained in:
Andrey Antukh 2021-06-09 14:47:40 +02:00 committed by Andrés Moya
parent 2202f90d74
commit 144127224c
4 changed files with 37 additions and 10 deletions

View file

@ -11,6 +11,7 @@
[app.common.geom.point :as gpt]
[app.common.spec :as us]
[app.common.transit :as t]
[app.common.uuid :as uuid]
[app.db.sql :as sql]
[app.metrics :as mtx]
[app.util.json :as json]
@ -366,3 +367,25 @@
(defn pgarray->vector
[v]
(vec (.getArray ^PgArray v)))
;; --- Locks
(defn- xact-check-param
[n]
(cond
(uuid? n) (uuid/get-word-high n)
(int? n) n
:else (throw (IllegalArgumentException. "uuid or number allowed"))))
(defn xact-lock!
[conn n]
(let [n (xact-check-param n)]
(exec-one! conn ["select pg_advisory_xact_lock(?::bigint) as lock" n])
true))
(defn xact-try-lock!
[conn n]
(let [n (xact-check-param n)
row (exec-one! conn ["select pg_try_advisory_xact_lock(?::bigint) as lock" n])]
(:lock row)))

View file

@ -43,8 +43,8 @@
([table where-params opts]
(let [opts (merge default-opts opts)
opts (cond-> opts
(:for-update opts)
(assoc :suffix "FOR UPDATE"))]
(:for-update opts) (assoc :suffix "FOR UPDATE")
(:for-key-share opts) (assoc :suffix "FOR KEY SHARE"))]
(sql/for-query table where-params opts))))
(defn update

View file

@ -268,8 +268,9 @@
(sv/defmethod ::update-file
[{:keys [pool] :as cfg} {:keys [id profile-id] :as params}]
(db/with-atomic [conn pool]
(let [{:keys [id] :as file} (db/get-by-id conn :file id {:for-update true})]
(let [{:keys [id] :as file} (db/get-by-id conn :file id {:for-key-share true})]
(files/check-edition-permissions! conn profile-id id)
(db/xact-lock! conn id)
(update-file (assoc cfg :conn conn)
(assoc params :file file)))))

View file

@ -6,13 +6,13 @@
(ns app.common.uuid
(:refer-clojure :exclude [next uuid zero?])
#?(:clj (:import java.util.UUID))
#?(:clj
(:require [clj-uuid :as impl]
[clojure.core :as c])
:cljs
(:require [app.common.uuid-impl :as impl]
[cljs.core :as c])))
(:require
[app.common.data :as d]
#?(:clj [clj-uuid :as impl])
#?(:clj [clojure.core :as c])
#?(:cljs [app.common.uuid-impl :as impl])
#?(:cljs [cljs.core :as c]))
#?(:clj (:import java.util.UUID)))
(def zero #uuid "00000000-0000-0000-0000-000000000000")
@ -45,3 +45,6 @@
(defn custom
([a] #?(:clj (UUID. 0 a) :cljs (c/uuid (impl/custom 0 a))))
([b a] #?(:clj (UUID. b a) :cljs (c/uuid (impl/custom b a)))))
#?(:clj
(d/export impl/get-word-high))