From c3a0db2431711d48863368434eeada3060d62f41 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 16 Apr 2024 14:52:37 +0200 Subject: [PATCH] :sparkles: Add the ability to schedule storage object touching as a task --- .../src/app/rpc/commands/files_thumbnails.clj | 2 +- backend/src/app/storage.clj | 26 ++++++++--- .../rpc_file_thumbnails_test.clj | 43 ++++++++++++++++++- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/backend/src/app/rpc/commands/files_thumbnails.clj b/backend/src/app/rpc/commands/files_thumbnails.clj index d766acd3c5..bd982ce171 100644 --- a/backend/src/app/rpc/commands/files_thumbnails.clj +++ b/backend/src/app/rpc/commands/files_thumbnails.clj @@ -271,7 +271,7 @@ (when (and (some? th1) (not= (:media-id th1) (:media-id th2))) - (sto/touch-object! storage (:media-id th1))) + (sto/touch-object! storage (:media-id th1) :async true)) th2)) diff --git a/backend/src/app/storage.clj b/backend/src/app/storage.clj index f6924aedb4..070c53f3fb 100644 --- a/backend/src/app/storage.clj +++ b/backend/src/app/storage.clj @@ -16,6 +16,7 @@ [app.storage.impl :as impl] [app.storage.s3 :as ss3] [app.util.time :as dt] + [app.worker :as wrk] [clojure.spec.alpha :as s] [datoteka.fs :as fs] [integrant.core :as ig] @@ -170,15 +171,28 @@ (impl/put-object object content)) object))) +(def ^:private default-touch-delay + "A default delay for the asynchronous touch operation" + (dt/duration "5m")) + (defn touch-object! "Mark object as touched." - [{:keys [::db/pool-or-conn] :as storage} object-or-id] + [{:keys [::db/pool-or-conn] :as storage} object-or-id & {:keys [async]}] (us/assert! ::storage storage) - (let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id) - rs (db/update! pool-or-conn :storage-object - {:touched-at (dt/now)} - {:id id})] - (pos? (db/get-update-count rs)))) + (let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id)] + (if async + (wrk/submit! ::wrk/conn pool-or-conn + ::wrk/task :object-update + ::wrk/delay default-touch-delay + :object :storage-object + :id id + :key :touched-at + :val (dt/now)) + (-> (db/update! pool-or-conn :storage-object + {:touched-at (dt/now)} + {:id id}) + (db/get-update-count) + (pos?))))) (defn get-object-data "Return an input stream instance of the object content." diff --git a/backend/test/backend_tests/rpc_file_thumbnails_test.clj b/backend/test/backend_tests/rpc_file_thumbnails_test.clj index f0cfc96375..11ed4f352e 100644 --- a/backend/test/backend_tests/rpc_file_thumbnails_test.clj +++ b/backend/test/backend_tests/rpc_file_thumbnails_test.clj @@ -277,8 +277,6 @@ (t/is (thrown? org.postgresql.util.PSQLException (th/db-delete! :storage-object {:id (:media-id row1)})))))) - - (t/deftest get-file-object-thumbnail (let [storage (::sto/storage th/*system*) profile (th/create-profile* 1) @@ -317,3 +315,44 @@ (let [result (:result out)] (t/is (contains? result "test-key-2")))))) + +(t/deftest create-file-object-thumbnail + (th/db-delete! :task {:name "object-update"}) + (let [storage (::sto/storage th/*system*) + profile (th/create-profile* 1) + file (th/create-file* 1 {:profile-id (:id profile) + :project-id (:default-project-id profile) + :is-shared false}) + data {::th/type :create-file-object-thumbnail + ::rpc/profile-id (:id profile) + :file-id (:id file) + :object-id "test-key-2" + :media {:filename "sample.jpg" + :mtype "image/jpeg"}}] + + (let [data (update data :media + (fn [media] + (-> media + (assoc :path (th/tempfile "backend_tests/test_files/sample2.jpg")) + (assoc :size 7923)))) + out (th/command! data)] + (t/is (nil? (:error out))) + (t/is (map? (:result out)))) + + (let [data (update data :media + (fn [media] + (-> media + (assoc :path (th/tempfile "backend_tests/test_files/sample.jpg")) + (assoc :size 312043)))) + out (th/command! data)] + (t/is (nil? (:error out))) + (t/is (map? (:result out)))) + + (let [[row1 :as rows] + (->> (th/db-query :task {:name "object-update"}) + (map #(update % :props db/decode-transit-pgobject)))] + + ;; (app.common.pprint/pprint rows) + (t/is (= 1 (count rows))) + (t/is (> (inst-ms (dt/diff (:created-at row1) (:scheduled-at row1))) + (inst-ms (dt/duration "4m")))))))