webapp: the settings dialogs stop holding on a spinner - #220
Draft
pythonlearner1025 wants to merge 1 commit into
Draft
webapp: the settings dialogs stop holding on a spinner#220pythonlearner1025 wants to merge 1 commit into
pythonlearner1025 wants to merge 1 commit into
Conversation
pythonlearner1025
force-pushed
the
feat/optimistic-held-dialogs
branch
from
September 5, 2026 07:15
ab0774c to
936777f
Compare
pythonlearner1025
changed the base branch from
feat/optimistic-members-machines
to
main
September 5, 2026 07:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What part this touches
Two dialogs in the webapp settings surface.
WorkspaceDetailsDialog.tsxsaves a workspace's name, default machine type,auto-provision flag and agent rule. It also adds and removes the repositories a
workspace clones.
AgentRulesPicker.tsxcreates, edits and deletes an agent rule, and selectswhich rule a workspace uses.
Both call the control plane and wait. This makes them answer at once.
Stacked on #205. Review that one first.
The gap
A user presses Save and the button says "Saving…" until the network answers.
Nothing else on screen changes. The same holds for adding a repository,
removing one, and every agent-rule action.
Five surfaces behave this way:
updateWorkspace, then dispatches.already holds the rule's UUID.
succeeds.
This is item 3 of the audit on #205: dialogs that hold on a spinner.
The fix
server returns.
whole list. A rejection removes the pending row and reports.
index so a rejection can put it back.
the UUID the client already has. The canonical rule replaces it.
The risk trade
Requests are not serialized. Two saves in flight together can settle out of
order, so an older response can briefly overwrite a newer optimistic view. The
next poll corrects it.
The alternative was a per-surface request queue. That is more machinery than
these dialogs justify: both are single-user settings screens where two writes
racing needs deliberate effort. Recording the limit here is the honest trade.
If it turns out to bite, the fix is a sequence number on the write, not a
queue.
Agent rules reuse the UUID the client already generates, so there is no
placeholder id to reconcile. That is why this PR needs nothing like the
pendingCreatemachinery #205 added for workspaces.Tests
Six tests in
packages/webapp/test/WorkspaceDetailsDialog.test.tsx, one persurface. Each drives a deferred promise, so it asserts the screen changed
BEFORE the request settled, and then asserts the restore on rejection. Both
directions, or the test proves nothing.
Each was seen failing with its own change reverted. For example:
Real counts on this branch: 116 webapp files pass, 1011 tests pass, 61 skip.
One
it.fails(...)inlody-toaster.test.tsxreports as an expected fail, asit does on
main.npm run lint:gatepasses at baseline. 66 anti-slop findings, 0 housefindings, 8 max-lines warnings. None moved.
npm run typecheck -w @blitzos/webapppasses.Deploy
The webapp bundle ships inside the control-plane worker. This branch is stacked
on #205 and must not merge before it.
After #205 merges, rebase this onto
mainand merge it. Merging tomainruns.github/workflows/canary.yml, which deploys the worker to canary. No box codechanged.
Verify after the merge:
Then open a workspace's settings, press Save, and watch the dialog answer
before the request finishes.
Rollback: