0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-14 19:19:09 -05:00

Move library-absorb operation to async task

And make it not mandatory in case of failure
This commit is contained in:
Andrey Antukh 2024-05-27 10:13:59 +02:00
parent 39119ac040
commit 574c8d1789
3 changed files with 70 additions and 59 deletions

View file

@ -823,7 +823,7 @@
(feat.fdata/persist-pointers! cfg file-id)))) (feat.fdata/persist-pointers! cfg file-id))))
(defn- absorb-library! (defn- absorb-library
"Find all files using a shared library, and absorb all library assets "Find all files using a shared library, and absorb all library assets
into the file local libraries" into the file local libraries"
[cfg {:keys [id] :as library}] [cfg {:keys [id] :as library}]
@ -841,7 +841,26 @@
:library-id (str id) :library-id (str id)
:files (str/join "," (map str ids))) :files (str/join "," (map str ids)))
(run! (partial absorb-library-by-file! cfg ldata) ids))) (run! (partial absorb-library-by-file! cfg ldata) ids)
library))
(defn absorb-library!
[{:keys [::db/conn] :as cfg} id]
(let [file (-> (get-file cfg id
:lock-for-update? true
:include-deleted? true)
(check-version!))
proj (db/get* conn :project {:id (:project-id file)}
{::db/remove-deleted false})
team (-> (db/get* conn :team {:id (:team-id proj)}
{::db/remove-deleted false})
(teams/decode-row))]
(-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-file-features! (:features file)))
(absorb-library cfg file)))
(defn- set-file-shared (defn- set-file-shared
[{:keys [::db/conn] :as cfg} {:keys [profile-id id] :as params}] [{:keys [::db/conn] :as cfg} {:keys [profile-id id] :as params}]
@ -854,25 +873,14 @@
;; file, we need to perform more complex operation, ;; file, we need to perform more complex operation,
;; so in this case we retrieve the complete file and ;; so in this case we retrieve the complete file and
;; perform all required validations. ;; perform all required validations.
(let [file (-> (get-file cfg id :lock-for-update? true) (let [file (-> (absorb-library! cfg id)
(check-version!) (assoc :is-shared false))]
(assoc :is-shared false))
team (teams/get-team conn
:profile-id profile-id
:project-id (:project-id file))]
(-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-client-features! (:features params))
(cfeat/check-file-features! (:features file)))
(absorb-library! cfg file)
(db/delete! conn :file-library-rel {:library-file-id id}) (db/delete! conn :file-library-rel {:library-file-id id})
(db/update! conn :file (db/update! conn :file
{:is-shared false {:is-shared false
:modified-at (dt/now)} :modified-at (dt/now)}
{:id id}) {:id id})
file) (select-keys file [:id :name :is-shared]))
(and (false? (:is-shared file)) (and (false? (:is-shared file))
(true? (:is-shared params))) (true? (:is-shared params)))
@ -936,26 +944,6 @@
[{:keys [::db/conn] :as cfg} {:keys [profile-id id] :as params}] [{:keys [::db/conn] :as cfg} {:keys [profile-id id] :as params}]
(check-edition-permissions! conn profile-id id) (check-edition-permissions! conn profile-id id)
(let [file (mark-file-deleted conn id)] (let [file (mark-file-deleted conn id)]
;; NOTE: when a file is a shared library, then we proceed to load
;; the whole file, proceed with feature checking and properly execute
;; the absorb-library procedure
(when (:is-shared file)
(let [file (-> (get-file cfg id
:lock-for-update? true
:include-deleted? true)
(check-version!))
team (teams/get-team conn
:profile-id profile-id
:project-id (:project-id file))]
(-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-client-features! (:features params))
(cfeat/check-file-features! (:features file)))
(absorb-library! cfg file)))
(rph/with-meta (rph/wrap) (rph/with-meta (rph/wrap)
{::audit/props {:project-id (:project-id file) {::audit/props {:project-id (:project-id file)
:name (:name file) :name (:name file)

View file

@ -503,10 +503,14 @@
(db/update! conn :file-tagged-object-thumbnail (db/update! conn :file-tagged-object-thumbnail
{:deleted-at nil} {:deleted-at nil}
{:file-id file-id})) {:file-id file-id})
:restored)
(defn- restore-project* (defn- restore-project*
[{:keys [::db/conn]} project-id] [{:keys [::db/conn] :as cfg} project-id]
(db/update! conn :project (db/update! conn :project
{:deleted-at nil} {:deleted-at nil}
@ -515,10 +519,12 @@
(doseq [{:keys [id]} (db/query conn :file (doseq [{:keys [id]} (db/query conn :file
{:project-id project-id} {:project-id project-id}
{::db/columns [:id]})] {::db/columns [:id]})]
(restore-file* conn id))) (restore-file* cfg id))
:restored)
(defn- restore-team* (defn- restore-team*
[{:keys [::db/conn]} team-id] [{:keys [::db/conn] :as cfg} team-id]
(db/update! conn :team (db/update! conn :team
{:deleted-at nil} {:deleted-at nil}
{:id team-id}) {:id team-id})
@ -530,7 +536,9 @@
(doseq [{:keys [id]} (db/query conn :project (doseq [{:keys [id]} (db/query conn :project
{:team-id team-id} {:team-id team-id}
{::db/columns [:id]})] {::db/columns [:id]})]
(restore-project* conn id))) (restore-project* cfg id))
:restored)
(defn restore-deleted-team! (defn restore-deleted-team!
"Mark a team and all related objects as not deleted" "Mark a team and all related objects as not deleted"

View file

@ -9,28 +9,42 @@
(:require (:require
[app.common.logging :as l] [app.common.logging :as l]
[app.db :as db] [app.db :as db]
[app.rpc.commands.files :as files]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[integrant.core :as ig])) [integrant.core :as ig]))
(def ^:dynamic *team-deletion* false)
(defmulti delete-object (defmulti delete-object
(fn [_ props] (:object props))) (fn [_ props] (:object props)))
(defmethod delete-object :file (defmethod delete-object :file
[{:keys [::db/conn]} {:keys [id deleted-at]}] [{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
(l/trc :hint "marking for deletion" :rel "file" :id (str id)) (l/trc :hint "marking for deletion" :rel "file" :id (str id))
;; Mark file media objects to be deleted (when-let [file (db/get* conn :file {:id id} {::db/remove-deleted false})]
(db/update! conn :file-media-object (when (and (:is-shared file)
{:deleted-at deleted-at} (not *team-deletion*))
{:file-id id}) ;; NOTE: we don't prevent file deletion on absorb operation failure
(try
(db/tx-run! cfg files/absorb-library! id)
(catch Throwable cause
(l/warn :hint "error on absorbing library"
:file-id id
:cause cause))))
;; Mark thumbnails to be deleted ;; Mark file media objects to be deleted
(db/update! conn :file-thumbnail (db/update! conn :file-media-object
{:deleted-at deleted-at} {:deleted-at deleted-at}
{:file-id id}) {:file-id id})
(db/update! conn :file-tagged-object-thumbnail ;; Mark thumbnails to be deleted
{:deleted-at deleted-at} (db/update! conn :file-thumbnail
{:file-id id})) {:deleted-at deleted-at}
{:file-id id})
(db/update! conn :file-tagged-object-thumbnail
{:deleted-at deleted-at}
{:file-id id})))
(defmethod delete-object :project (defmethod delete-object :project
[{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}] [{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
@ -49,12 +63,13 @@
{:deleted-at deleted-at} {:deleted-at deleted-at}
{:team-id id}) {:team-id id})
(doseq [project (db/update! conn :project (binding [*team-deletion* true]
{:deleted-at deleted-at} (doseq [project (db/update! conn :project
{:team-id id} {:deleted-at deleted-at}
{::db/return-keys [:id :deleted-at] {:team-id id}
::db/many true})] {::db/return-keys [:id :deleted-at]
(delete-object cfg (assoc project :object :project)))) ::db/many true})]
(delete-object cfg (assoc project :object :project)))))
(defmethod delete-object :default (defmethod delete-object :default
[_cfg props] [_cfg props]