mirror of
https://github.com/penpot/penpot.git
synced 2026-11-12 04:50:42 +00:00
The comment on the branch limits said the header requires a queue on every entry. Nothing requires one at runtime: climit.clj::wrap skips a declared limit with no configuration and logs a warning. Only the test example-config-bounds-every-wait checks this file for a queue, and the numbers are example defaults, not measurements. AI-assisted-by: claude-opus-5-5
209 lines
8.6 KiB
Clojure
209 lines
8.6 KiB
Clojure
;; Example climit.edn file
|
|
;; Required: permits
|
|
;; Optional: queue, omitted means Integer/MAX_VALUE (unbounded)
|
|
;; 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, 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 and a queue: a command takes the
|
|
;; limits it declares before the root ones, so the queue of a limit is where
|
|
;; its own pile-up waits. The root limits bound what runs at the same time,
|
|
;; not what waits for it.
|
|
;; The production file lives outside this repository: mirror the shape there,
|
|
;; not these numbers. It has to list every id a command declares: an id without
|
|
;; an entry runs with no limiter at all.
|
|
{:update-file/global
|
|
{:permits 20 :queue 50 :timeout 60000}
|
|
:update-file/by-profile
|
|
{:permits 1 :queue 5 :timeout 60000}
|
|
|
|
:process-font/global
|
|
{:permits 4 :queue 10 :timeout 60000}
|
|
:process-font/by-profile
|
|
{:permits 1 :queue 5 :timeout 60000}
|
|
|
|
:process-image/global
|
|
{:permits 8 :queue 20 :timeout 60000}
|
|
:process-image/by-profile
|
|
{:permits 1 :queue 5 :timeout 60000}
|
|
|
|
:auth/global
|
|
{:permits 8 :queue 20 :timeout 30000}
|
|
|
|
:root/global
|
|
{:permits 40 :queue 100 :timeout 30000}
|
|
|
|
:root/by-profile
|
|
{:permits 10 :queue 30 :timeout 30000}
|
|
|
|
:file-thumbnail-ops/global
|
|
{:permits 20 :queue 50 :timeout 60000}
|
|
:file-thumbnail-ops/by-profile
|
|
{:permits 2 :queue 10 :timeout 60000}
|
|
|
|
:submit-audit-events/by-profile
|
|
{:permits 1 :queue 3 :timeout 30000}
|
|
|
|
:restore-file-snapshot/global
|
|
{:permits 3 :queue 5 :timeout 60000}
|
|
|
|
:restore-file-snapshot/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
:create-file-snapshot/global
|
|
{:permits 3 :queue 5 :timeout 60000}
|
|
|
|
:create-file-snapshot/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
:send-user-feedback/global
|
|
{:permits 4 :queue 10 :timeout 30000}
|
|
|
|
:send-user-feedback/by-profile
|
|
{:permits 1 :queue 3 :timeout 30000}
|
|
|
|
:import-binfile/global
|
|
{:permits 4 :queue 10 :timeout 60000}
|
|
|
|
:import-binfile/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
:create-import-binfile-job/global
|
|
{:permits 4 :queue 10 :timeout 60000}
|
|
|
|
:create-import-binfile-job/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
:profile-plugin-ops/by-profile
|
|
{:permits 1 :queue 2 :timeout 30000}
|
|
|
|
;; Every limit below is provisional. The container that runs the preview
|
|
;; has no heap cap: `docker/devenv/files/entrypoint.sh` and
|
|
;; `backend/scripts/_env` both replace JAVA_OPTS without `-Xmx`, and the
|
|
;; live JVM command line carries none, so the budget is the JVM default
|
|
;; and it is unmeasured. The permit counts are derived from the
|
|
;; neighbours above instead of from a memory figure, and they stay
|
|
;; provisional until a peak-heap measurement of a cold compare on the
|
|
;; design-system file replaces them.
|
|
;;
|
|
;; The anchor is the snapshot pair above: `:create-file-snapshot/global`
|
|
;; admits three whole-file operations at once, each realizing one
|
|
;; document and writing one snapshot, and `:restore-file-snapshot/global`
|
|
;; admits the same three for an operation that also writes a rollback
|
|
;; snapshot and the older payload back into the file. A branch operation
|
|
;; realizes more than one document, so it has to admit fewer at once to
|
|
;; keep the same number of realized documents in flight.
|
|
;;
|
|
;; What each operation holds, read from the code:
|
|
;; * `create-file-branch` realizes main once and writes one snapshot
|
|
;; (`backend/src/app/rpc/commands/files_branch.clj::create-file-branch`),
|
|
;; which is the anchor's shape and the anchor's cost.
|
|
;; * `merge-file-branch` and `update-branch-from-main` hold three
|
|
;; realized documents at once: main, the derived branch, and the base
|
|
;; snapshot (`files_branch.clj::merge-file-branch`,
|
|
;; `files_branch.clj::update-branch-from-main`). Both also write a
|
|
;; snapshot and a whole file payload, and the update computes a
|
|
;; second diff for the squash, so they earn the tightest count.
|
|
;; * `materialize-file-branch` realizes the branch and the libraries it
|
|
;; validates against, then writes the whole payload
|
|
;; (`files_branch.clj::materialize-file-branch`), so it sits between
|
|
;; the anchor and the merge pair.
|
|
;; * `create-pull-request` and `update-pull-request-snapshot` realize the
|
|
;; branch once and write one review snapshot
|
|
;; (`files_pull_request.clj::create-pull-request`,
|
|
;; `files_pull_request.clj::update-pull-request-snapshot`), which is
|
|
;; the anchor's shape again.
|
|
;;
|
|
;; The numbers here are example defaults, not measurements. Every entry
|
|
;; of this file carries a queue because `climit_test.clj` checks this
|
|
;; file for one; at runtime a limit with no entry is skipped with a
|
|
;; warning (`climit.clj::wrap`). The write-side global queues
|
|
;; follow the anchor's ratio of five waiters to three permits, rounded
|
|
;; up. The per-profile entry of one permit and a queue of two keeps a
|
|
;; single designer to one operation at a time. The two read-side
|
|
;; entries are generous by design, with the ratio of
|
|
;; `:update-file/global` (fifty waiters to twenty permits), 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 :queue 5 :timeout 60000}
|
|
|
|
:create-file-branch/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
;; A merge holds three realized documents, a snapshot write, and a
|
|
;; 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 :queue 2 :timeout 60000}
|
|
|
|
:merge-file-branch/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
;; An update from main holds the same three documents and pays for a
|
|
;; snapshot write and a squash diff on top, so it takes the merge's
|
|
;; count. Provisional.
|
|
:update-branch-from-main/global
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
:update-branch-from-main/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
;; Materialize realizes one document plus its libraries and writes the
|
|
;; payload, which is cheaper than a merge and dearer than the anchor,
|
|
;; so it admits two where the merge admits one and the anchor admits
|
|
;; three. Provisional.
|
|
:materialize-file-branch/global
|
|
{:permits 2 :queue 4 :timeout 60000}
|
|
|
|
:materialize-file-branch/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
;; A cold listing realizes main once and derives every uncached branch,
|
|
;; which makes it the slowest read of the preview. It runs when a user
|
|
;; opens the workspace branch switcher, the all-branches dialog, or the
|
|
;; dashboard branches popover; a file open only counts branches, through
|
|
;; `get-file-branch-count`, which takes no limit. Six at once is above
|
|
;; what those opens need under normal use, and six three-document
|
|
;; operations hold eighteen realized documents, below the twenty
|
|
;; one-document saves `:update-file/global` above already admits.
|
|
;; Provisional.
|
|
:get-file-branches/global
|
|
{:permits 6 :queue 15 :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 :queue 15 :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 :queue 5 :timeout 60000}
|
|
|
|
:create-pull-request/by-profile
|
|
{:permits 1 :queue 2 :timeout 60000}
|
|
|
|
;; Publishing the branch state also realizes the branch and pins one
|
|
;; snapshot. The command declares a single instance-wide queue
|
|
;; (`files_pull_request.clj::update-pull-request-snapshot`), so the
|
|
;; bounded wait sits on the global entry here rather than on a
|
|
;; per-profile entry. Provisional.
|
|
:update-pull-request-snapshot/global
|
|
{:permits 3 :queue 4 :timeout 60000}}
|