Repository navigation
fix: a drop during card migration no longer duplicates the card (MS-27523) - #243
Merged
Merged
Conversation
…7523) PDCardDeckGroup migrated cards between decks on drag-enter, awaiting the browser part way through (cancelling animations), and ran the drop's transformation and refresh without waiting for it. A drop landing in that gap refreshed the destination from data that already held the card, then the migration resumed and inserted it again, so the deck held the same card twice and the render threw 'More than one sibling ... has the same key value', terminating the Blazor Server circuit. Every deck also listens for the drop on the document, so the transformation ran once per deck. Migration, drop and end of drag now take one lock, so a drop waits for the migration and later drops find the drag already over. Reproduced in a real browser on the demo kanban (circuit killed on the first drop) and verified fixed over 3 x 40 drags. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 6 |
🟢 Coverage 100.00% diff coverage · +0.00% coverage variation
Metric Results Coverage variation ✅ +0.00% coverage variation Diff coverage ✅ 100.00% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (8f35684) 16054 16031 99.86% Head commit (dea0e15) 16056 (+2) 16033 (+2) 99.86% (+0.00%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#243) 2 2 100.00% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
AI Reviewer: run a review on demand. To trigger the first review automatically, go to your organization or repository integration settings. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.
Summary
Dropping a card shortly after entering a column could terminate the Blazor Server circuit. Seen in production on a Magic Suite Kanban board (MS-27523); reproduced here on the demo kanban, where the first drop killed the circuit every time.
Cause
PDCardDeckGroupmigrates cards between decks on drag-enter.RemoveSelectedCardsAsyncawaits the browser part way through (cancelling animations), and the drop'sInitiateTransformAsyncran without waiting for it. A drop landing in that gap ran the transformation and refreshed the destination from data that already held the card; the migration then resumed and inserted the card a second time. The next render threwMore than one sibling of component 'PDCard' has the same key value, which is an unhandled circuit exception.Separately, every deck registers its own document-level
droplistener, so the transformation ran once per deck (up to eight times on the demo page).Fix
Migration, drop and end of drag take one
SemaphoreSlim. A drop waits for an in-flight migration, and later drops from the other decks find the drag already over and return.Evidence
Group_DropDuringTheMigration_PutsTheCardInTheDestinationOnce,Group_DropReachingEveryDeck_TransformsOnce. Full suite: 3801 passed./pdcarddeckgroup): before, circuit terminated on the first drop in 3 of 3 runs and the server loggedUnhandled exception in circuit; after, 3 x 40 drags, 0 console errors, 0 server circuit errors, cards back where they started.Not covered
Timing on a high-latency link. The race window is the JS round trip, so it is wider in production than on localhost; the tests force the interleaving rather than rely on timing.
🤖 Generated with Claude Code