fix(ui): a double-click on Trigger Auto Integrate sent two mutations - #277
Open
logicflakes wants to merge 1 commit into
Open
fix(ui): a double-click on Trigger Auto Integrate sent two mutations#277logicflakes wants to merge 1 commit into
logicflakes wants to merge 1 commit into
Conversation
autoIntegrateFeatureSet is not idempotent. Server-side it gathers each dependency's latest release, asks whether a matching product release already exists, and creates one if not -- a check-then-act that takes no lock, so two in-flight calls can both find nothing and both create a product release. The control is a plain n-icon with an @click handler: no built-in disabled or loading state, and the handler had no re-entry guard. A double-click therefore fired two concurrent mutations. Guards on an in-flight ref and reflects it in the control: reduced opacity and a not-allowed cursor while running, with the tooltip switching to "Auto Integrate in progress...". Reset in a finally, not after the notify, so a failed mutation cannot leave the button permanently dead. Chosen over locking the feature set server-side. That was implemented and measured -- four concurrent calls did produce four product releases -- but the evidence did not justify it: zero feature sets in sandbox data have two product releases sharing a parent set, so the path being unguarded had never actually caused harm. The server-side lock would also have been held across external I/O (GitHub build trigger, email send), newly blocking the AUTOMATIC integrator for that feature set until a 30s lock timeout. Trading a real new failure mode for a theoretical one was the wrong direction; a double-click is the realistic trigger and this covers it with no locking. See rearm-saas#408 (closed) for the full analysis. No new lint violations: the file's error count is unchanged from main at 273 (pre-existing, repo-wide). UI build clean. Co-Authored-By: Claude <noreply@anthropic.com> ReARM-Agent: 1420896f-adf5-4843-896f-d863cfcc6528 ReARM-Agentic-Session: 4477ca5a-8dfc-435b-804c-952d39345110
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.
The problem
autoIntegrateFeatureSetis not idempotent. Server-side it gathers each dependency's latest release, asks whether a matching product release already exists, and creates one if not — a check-then-act that takes no lock, so two in-flight calls can both find nothing and both create a product release.The control is a plain
n-iconwith an@clickhandler: no built-in disabled or loading state, and the handler had no re-entry guard. A double-click fired two concurrent mutations.The fix
Guards on an in-flight ref and reflects it in the control — reduced opacity,
not-allowedcursor, and the tooltip switching to "Auto Integrate in progress...".Reset in a
finally, not after the notify, so a failed mutation cannot leave the button permanently dead.Why this instead of a server-side lock
The server-side fix was implemented and measured (relizaio/rearm-saas#408, now closed): four concurrent calls did produce four product releases. But the evidence did not justify shipping it:
createProductRelease -> createRelease, which performs synchronous external I/O (GitHub build trigger, email send). A stalled user request would then block the automatic integrator for that feature set until a 30s lock timeout — a failure mode that does not exist today.Trading a real new failure mode for a theoretical one was the wrong direction. A double-click is the realistic trigger, and this covers it with no locking, no new coupling, and no risk to the version pipeline.
Checks
trywithout re-indenting; fixed.Co-Authored-By: Claude noreply@anthropic.com
🤖 Generated with Claude Code