From 6ddbfcf749fdc6ef8ff16451deb40f4908dc5a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Tejero-Cantero?= <807608+alvorithm@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:19:38 +0200 Subject: [PATCH] :bug: Make the backend branch tests pass on iop-vc-preview (#12568) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :bug: Give the branch concurrency limits a timeout Every global entry for branch and pull-request commands lacked a :timeout, so a saturated limiter parked its waiters forever and climit-test/example-config-bounds-every-wait failed on seven ids. Each entry now waits at most 60 s, the value of the other slow operations. The size gates in files_branch.clj refuse files whose operation would exceed 30 s, so the wait covers one in-flight operation with as much again in margin. AI-assisted-by: claude-opus-5-5 Signed-off-by: Álvaro Tejero Cantero * :bug: Make the quota racer a member of the file team File access requires membership of the file's team since the permission check started joining team_profile_rel. The racer in create-checks-the-branch-quota-inside-the-lock held only a file role, so its create failed with :object-not-found and the test never raced. The racer now joins the file's team as an editor, so both creates again compete for the last branch slot. AI-assisted-by: claude-opus-5-5 Signed-off-by: Álvaro Tejero Cantero --------- Signed-off-by: Álvaro Tejero Cantero --- backend/resources/climit.edn | 43 +++++++++++-------- .../rpc_file_branch_oplog_test.clj | 6 ++- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/backend/resources/climit.edn b/backend/resources/climit.edn index 01f4b57d51..660d2abca6 100644 --- a/backend/resources/climit.edn +++ b/backend/resources/climit.edn @@ -4,7 +4,7 @@ ;; Optional: timeout in milliseconds, omitted means the thread waits for a ;; permit forever, and a saturated limiter parks it for good. Values below: ;; 60s for operations that can be slow (file updates, images, fonts, thumbnails, -;; snapshots, imports) and 30s for the rest. +;; snapshots, imports, branches, pull requests) and 30s for the rest. ;; Note: a queue bounds how many waiters pile up, a timeout bounds how long one ;; waiter waits. Every entry sets a timeout; the by-profile ones also set a ;; queue, which is where a pile-up hurts. @@ -113,22 +113,29 @@ ;; `files_pull_request.clj::update-pull-request-snapshot`), which is ;; the anchor's shape again. ;; - ;; The write-side operations carry a queue and a timeout so that a - ;; refusal follows a bounded wait rather than arriving instantly. The - ;; queue sits on the per-profile entry, following the anchor, and on the - ;; global entry where the command declares no per-profile queue. The - ;; per-profile entry of one permit keeps a single designer to one - ;; operation at a time. The two read-side entries are generous by design - ;; and carry no queue and no timeout, so a panel open waits for its turn - ;; instead of being refused: six three-document comparisons hold - ;; eighteen realized documents, fewer than the twenty one-document saves - ;; `:update-file/global` already admits. + ;; The write-side operations carry a queue so that a refusal follows a + ;; bounded wait rather than arriving instantly. The queue sits on the + ;; per-profile entry, following the anchor, and on the global entry + ;; where the command declares no per-profile queue. The per-profile + ;; entry of one permit keeps a single designer to one operation at a + ;; time. The two read-side entries are generous by design and carry no + ;; queue, so a panel open waits for its turn instead of being refused: + ;; six three-document comparisons hold eighteen realized documents, + ;; fewer than the twenty one-document saves `:update-file/global` + ;; already admits. + ;; + ;; Every entry below, global and per-profile, read and write, takes the + ;; 60 s timeout of the slow operations above. The size gates in + ;; `backend/src/app/rpc/commands/files_branch.clj` refuse any file large + ;; enough for an operation to exceed 30 s, with the measured limit + ;; halved, so a 60 s wait covers one in-flight operation at that + ;; ceiling with as much again in margin. ;; create-file-branch realizes main and writes one snapshot, the shape ;; of `:create-file-snapshot` above, so it takes the anchor's numbers ;; unchanged. Provisional. :create-file-branch/global - {:permits 3} + {:permits 3 :timeout 60000} :create-file-branch/by-profile {:permits 1 :queue 2 :timeout 60000} @@ -137,7 +144,7 @@ ;; whole-file write into main, so one instance-wide operation holds the ;; anchor's whole three-permit budget on its own. Provisional. :merge-file-branch/global - {:permits 1} + {:permits 1 :timeout 60000} :merge-file-branch/by-profile {:permits 1 :queue 2 :timeout 60000} @@ -146,7 +153,7 @@ ;; snapshot write and a squash diff on top, so it takes the merge's ;; count. Provisional. :update-branch-from-main/global - {:permits 1} + {:permits 1 :timeout 60000} :update-branch-from-main/by-profile {:permits 1 :queue 2 :timeout 60000} @@ -156,7 +163,7 @@ ;; so it admits two where the merge admits one and the anchor admits ;; three. Provisional. :materialize-file-branch/global - {:permits 2} + {:permits 2 :timeout 60000} :materialize-file-branch/by-profile {:permits 1 :queue 2 :timeout 60000} @@ -168,18 +175,18 @@ ;; one-document saves `:update-file/global` above already admits. ;; Provisional. :get-file-branches/global - {:permits 6} + {:permits 6 :timeout 60000} ;; The compare dialog's query holds main, the derived branch, and the ;; base at once, the same three documents the listing holds, so it takes ;; the same count. Provisional. :get-branch-diff/global - {:permits 6} + {:permits 6 :timeout 60000} ;; Creating a pull request realizes the branch and pins one review ;; snapshot, the anchor's shape. Provisional. :create-pull-request/global - {:permits 3} + {:permits 3 :timeout 60000} :create-pull-request/by-profile {:permits 1 :queue 2 :timeout 60000} diff --git a/backend/test/backend_tests/rpc_file_branch_oplog_test.clj b/backend/test/backend_tests/rpc_file_branch_oplog_test.clj index c5a1126f59..d7996a0086 100644 --- a/backend/test/backend_tests/rpc_file_branch_oplog_test.clj +++ b/backend/test/backend_tests/rpc_file_branch_oplog_test.clj @@ -657,8 +657,10 @@ :is-shared false}) file-id (:id file) ;; the racer is a second designer: the per-profile climit - ;; serializes one designer's creates against themselves - _ (th/create-file-role* {:file-id file-id + ;; serializes one designer's creates against themselves. File + ;; access requires membership of the file's team, so the racer + ;; joins that team as an editor. + _ (th/create-team-role* {:team-id (:default-team-id profile1) :profile-id (:id profile2) :role :editor}) real-lock db/xact-lock!