Fix clogged up git operations.

This commit is contained in:
Greyson Parrelli
2026-08-27 13:32:47 -04:00
parent 2e3af19d00
commit d7452c2262
9 changed files with 315 additions and 51 deletions
+26 -7
View File
@@ -897,7 +897,7 @@ The endpoints, all under `/t/<tabId>/api`:
| `GET repo` | the repository, its refs, the comment counts, and the diff selection on screen |
| `POST repo/context` | what the page publishes when you change the base ref |
| `GET diff` | `base`, `uncommitted`, `commit`, `force`, `ignoreWhitespace` |
| `GET diff/revision` | a digest of what that same selection resolves to now — one hash, so the page can poll it |
| `GET diff/revision` | a digest of what that same selection resolves to now — one hash, so the page can poll it; 503 while git is busy with work someone is waiting on |
| `GET file` | a file's contents at a ref, for expanding collapsed context |
| `GET/POST comments` | list, or open a thread |
| `PATCH/DELETE comments/{id}` | edit or delete one |
@@ -923,12 +923,31 @@ itself is not that answer: it would lose your scroll position, your place in a
hunk, and whatever you had half-typed into a composer.
So the page asks `GET diff/revision` every few seconds — a hash of the patch plus
`HEAD`, which is cheap enough to ask for on a timer and catches both an
uncommitted edit and work being committed out from under the range. When it stops
matching the revision the diff came with, a banner says so and offers the refresh.
Dismissing it keeps the diff you are reading and re-arms against what is there
now, so the *next* change tells you too. Polling stops while the pane is hidden,
and starts again the moment it comes back.
`HEAD`, which catches both an uncommitted edit and work being committed out from
under the range. When it stops matching the revision the diff came with, a banner
says so and offers the refresh. Dismissing it keeps the diff you are reading and
re-arms against what is there now, so the *next* change tells you too. Polling
stops while the pane is hidden, and starts again the moment it comes back.
The poll is a `git diff`, though, and the interesting case is a review open in
seven tabs on a repository that is being built in the terminal pane next door.
Left to a fixed interval, that is a git process running in this app most of the
time, and the agent's `GET diff` waits behind polls whose answers nobody is
reading.
So the server sorts git into two kinds of work and only ever holds one of them
up. Anything with somebody on the other end of it — a diff being opened, the
**Refresh** you just clicked, an agent fetching the patch it is about to review —
runs the moment it arrives, every time, and is never queued behind anything. A
poll runs only while nothing is being waited on and the app is not already busy
with a few of them; otherwise it is turned away with a 503 on the spot. That
costs nothing, because a poll has no answer anybody is waiting for, and it means
a click does not merely jump the queue — it clears the field of polls for as long
as it takes.
Each pane also spaces its own next poll by what the last one actually cost, so a
pane on a slow repository asks less often on its own, and a refused one waits
longer still. A pane on a small repository never notices any of it.
Comments are the other half, and they work the other way round: those arrive over
`GET events` and are applied live, because a thread appearing in the rail doesn't