From 57ed11942c29b8ce49932848aa29b3bb4f01e39b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 13 Oct 2026 18:44:40 +0000 Subject: [PATCH] :bug: Fix the broken restore test and the flaky climit test The merge of main into staging brought the closed storage metadata schema, which requires file-id and id on file-data objects. The restore test built one without those keys, so it failed with an invalid metadata error. Its helper now takes extra metadata and the test passes the ids of the file and of its file-data row, as production does. The republish test asserted the exact list of waiting-gauge publications, but the component's sampler starts its first tick right away and under load lands inside the recorded window, publishing the same count twice. The test now builds the counters alone, so the republish call is the only publisher. AI-assisted-by: deepseek-v4.1-flash --- backend/test/backend_tests/climit_test.clj | 21 ++++++++++--------- .../restore_storage_objects_test.clj | 20 +++++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/backend/test/backend_tests/climit_test.clj b/backend/test/backend_tests/climit_test.clj index c0d82344ef..a7c89cb38f 100644 --- a/backend/test/backend_tests/climit_test.clj +++ b/backend/test/backend_tests/climit_test.clj @@ -650,18 +650,19 @@ (t/deftest republish-writes-the-current-waiting-count ;; A call that never comes back keeps the count up, but if it is also the ;; last thing that happened nothing rewrites that series and it goes stale in - ;; the scrape. The republish is what keeps it visible. - (th/with-climit [climit {:test-republish/by-profile {:permits 1 :timeout 3000}}] - (let [name (limiter-name :test-republish/by-profile)] + ;; the scrape. The republish is what keeps it visible. The counters are built + ;; on their own: with a component, its sampler would also publish the same + ;; count the moment its first tick lands inside the window. + (let [counters (#'climit/create-waiting-counters) + name (limiter-name :test-republish/by-profile) + counter ^java.util.concurrent.atomic.AtomicLong (#'climit/waiting-counter counters name)] - (.set ^java.util.concurrent.atomic.AtomicLong - (#'climit/waiting-counter (:counters climit) name) - 3) + (.set counter 3) - (record-metrics - (fn [] - (#'climit/republish-waiting (th/metrics-stub) (:counters climit)) - (t/is (= [3] (waiting-value-of name)))))))) + (record-metrics + (fn [] + (#'climit/republish-waiting (th/metrics-stub) counters) + (t/is (= [3] (waiting-value-of name))))))) (t/deftest halting-the-component-stops-the-republisher ;; The republisher is a daemon thread started with the component: halting it diff --git a/backend/test/backend_tests/restore_storage_objects_test.clj b/backend/test/backend_tests/restore_storage_objects_test.clj index 5545270648..5986170b20 100644 --- a/backend/test/backend_tests/restore_storage_objects_test.clj +++ b/backend/test/backend_tests/restore_storage_objects_test.clj @@ -24,11 +24,14 @@ ;; hits the foreign key and skips them forever. (defn- put-object! - [bucket] - (sto/put-object! (::sto/storage th/*system*) - {::sto/content (sto/content "sobject") - :content-type "text/plain" - :bucket bucket})) + ([bucket] + (put-object! bucket {})) + ([bucket metadata] + (sto/put-object! (::sto/storage th/*system*) + (merge {::sto/content (sto/content "sobject") + :content-type "text/plain" + :bucket bucket} + metadata)))) (defn- find-object [id] @@ -86,8 +89,11 @@ (let [profile (th/create-profile* 1) file (th/create-file* 1 {:profile-id (:id profile) :project-id (:default-project-id profile)}) - sobject (:id (put-object! "file-data")) - data-id (uuid/next)] + data-id (uuid/next) + ;; file-data objects carry the ids of their row: the GC resolves the + ;; reference with that pair. + sobject (:id (put-object! "file-data" {:file-id (:id file) + :id data-id}))] (th/db-update! :file {:deleted-at (ct/in-past {:days 1})} {:id (:id file)}) (th/db-insert! :file-data