0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-08 07:50:43 -05:00

Reduce lock contention on uploading file object thumbnail

This commit is contained in:
Andrey Antukh 2024-04-16 11:04:16 +02:00
parent 4dacba6836
commit 56ba32b66d
2 changed files with 44 additions and 49 deletions

View file

@ -228,51 +228,52 @@
;; MUTATION COMMANDS ;; MUTATION COMMANDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MUTATION COMMAND: create-file-object-thumbnail (def sql:get-file-object-thumbnail
"SELECT * FROM file_tagged_object_thumbnail
WHERE file_id = ? AND object_id = ? AND tag = ?
FOR UPDATE")
(defn- create-file-object-thumbnail! (def sql:create-file-object-thumbnail
[{:keys [::db/conn ::sto/storage]} file-id object-id media tag] "INSERT INTO file_tagged_object_thumbnail (file_id, object_id, tag, media_id)
VALUES (?, ?, ?, ?)
ON CONFLICT (file_id, object_id, tag)
DO UPDATE SET updated_at=?, media_id=?, deleted_at=null
RETURNING *")
(let [thumb (db/get* conn :file-tagged-object-thumbnail (defn- persist-thumbnail!
{:file-id file-id [storage media created-at]
:object-id object-id (let [path (:path media)
:tag tag}
{::db/remove-deleted false
::sql/for-update true})
path (:path media)
mtype (:mtype media) mtype (:mtype media)
hash (sto/calculate-hash path) hash (sto/calculate-hash path)
data (-> (sto/content path) data (-> (sto/content path)
(sto/wrap-with-hash hash)) (sto/wrap-with-hash hash))]
tnow (dt/now)
media (sto/put-object! storage (sto/put-object! storage
{::sto/content data {::sto/content data
::sto/deduplicate? true ::sto/deduplicate? true
::sto/touched-at tnow ::sto/touched-at created-at
:content-type mtype :content-type mtype
:bucket "file-object-thumbnail"})] :bucket "file-object-thumbnail"})))
(if (some? thumb)
(do
;; We mark the old media id as touched if it does not matches (defn- create-file-object-thumbnail!
(when (not= (:id media) (:media-id thumb)) [{:keys [::sto/storage] :as cfg} file-id object-id media tag]
(sto/touch-object! storage (:media-id thumb))) (let [tsnow (dt/now)
(db/update! conn :file-tagged-object-thumbnail media (persist-thumbnail! storage media tsnow)
{:media-id (:id media) [th1 th2] (db/tx-run! cfg (fn [{:keys [::db/conn]}]
:deleted-at nil (let [th1 (db/exec-one! conn [sql:get-file-object-thumbnail file-id object-id tag])
:updated-at tnow} th2 (db/exec-one! conn [sql:create-file-object-thumbnail
{:file-id file-id file-id object-id tag (:id media)
:object-id object-id tsnow (:id media)])]
:tag tag})) [th1 th2])))]
(db/insert! conn :file-tagged-object-thumbnail
{:file-id file-id (when (and (some? th1)
:object-id object-id (not= (:media-id th1)
:created-at tnow (:media-id th2)))
:updated-at tnow (sto/touch-object! storage (:media-id th1)))
:tag tag
:media-id (:id media)})))) th2))
(def ^:private (def ^:private
schema:create-file-object-thumbnail schema:create-file-object-thumbnail
@ -296,16 +297,10 @@
(media/validate-media-type! media) (media/validate-media-type! media)
(media/validate-media-size! media) (media/validate-media-size! media)
(db/tx-run! cfg (db/run! cfg files/check-edition-permissions! profile-id file-id)
(fn [{:keys [::db/conn] :as cfg}]
(files/check-edition-permissions! conn profile-id file-id) (let [cfg (update cfg ::sto/storage media/configure-assets-storage)]
(when-not (db/read-only? conn) (create-file-object-thumbnail! cfg file-id object-id media (or tag "frame"))))
(let [cfg (-> cfg
(update ::sto/storage media/configure-assets-storage)
(assoc ::rtry/when rtry/conflict-exception?)
(assoc ::rtry/max-retries 5)
(assoc ::rtry/label "create-file-object-thumbnail"))]
(create-file-object-thumbnail! cfg file-id object-id media (or tag "frame")))))))
;; --- MUTATION COMMAND: delete-file-object-thumbnail ;; --- MUTATION COMMAND: delete-file-object-thumbnail

View file

@ -1158,7 +1158,7 @@
;; check that the unknown frame thumbnail is deleted ;; check that the unknown frame thumbnail is deleted
(let [rows (th/db-query :file-tagged-object-thumbnail {:file-id (:id file)})] (let [rows (th/db-query :file-tagged-object-thumbnail {:file-id (:id file)})]
(t/is (= 2 (count rows))) (t/is (= 2 (count rows)))
(t/is (= 1 (count (remove (comp some? :deleted-at) rows))))) (t/is (= 1 (count (remove :deleted-at rows)))))
(let [res (th/run-task! :objects-gc {:min-age 0})] (let [res (th/run-task! :objects-gc {:min-age 0})]
(t/is (= 3 (:processed res)))) (t/is (= 3 (:processed res))))