🐛 Make the backend branch tests pass on iop-vc-preview (#12568)

* 🐛 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 <alvorithm@teje.ro>

* 🐛 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 <alvorithm@teje.ro>

---------

Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit is contained in:
Álvaro Tejero-Cantero 2026-10-22 19:19:38 +02:00 committed by GitHub
parent 1c8e4ffe9d
commit 6ddbfcf749
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 20 deletions

View File

@ -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}

View File

@ -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!