Skip to content

fix(ui): a double-click on Trigger Auto Integrate sent two mutations - #277

Open
logicflakes wants to merge 1 commit into
mainfrom
2026-08-trigger-auto-integrate-double-click
Open

fix(ui): a double-click on Trigger Auto Integrate sent two mutations#277
logicflakes wants to merge 1 commit into
mainfrom
2026-08-trigger-auto-integrate-double-click

Conversation

@logicflakes

Copy link
Copy Markdown
Contributor

The problem

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 fired two concurrent mutations.

The fix

Guards on an in-flight ref and reflects it in the control — reduced opacity, not-allowed cursor, 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:

  • Zero feature sets in sandbox data have two product releases sharing a parent set — the path being unguarded had never actually caused harm. The 4/4 number came from a synthetic four-thread harness, not a realistic scenario.
  • The lock would have been held across 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

  • UI build clean.
  • No new lint violations — the repo's error count is unchanged from main at 273 (pre-existing, repo-wide). My first attempt added 13 by wrapping the body in try without re-indenting; fixed.

Co-Authored-By: Claude noreply@anthropic.com

🤖 Generated with Claude Code

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant