CODAP-1117: fix MobX constraint violation in Collection.completeCaseGroups#2398
CODAP-1117: fix MobX constraint violation in Collection.completeCaseGroups#2398
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2398 +/- ##
==========================================
+ Coverage 85.52% 85.53% +0.01%
==========================================
Files 758 758
Lines 42157 42169 +12
Branches 10439 10048 -391
==========================================
+ Hits 36054 36069 +15
+ Misses 6091 6088 -3
Partials 12 12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
codap-v3
|
||||||||||||||||||||||||||||
| Project |
codap-v3
|
| Branch Review |
main
|
| Run status |
|
| Run duration | 05m 21s |
| Commit |
|
| Committer | Kirk Swenson |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
73
|
|
|
0
|
|
|
300
|
| View all changes introduced in this branch ↗︎ | |
2d60331 to
8b22e94
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes a MobX constraint violation in Collection.completeCaseGroups() by replacing 5 observable boxes with plain variables and a single observable version counter. The change maintains the same functionality while ensuring MobX constraints are respected by only writing to observables from action contexts.
Changes:
- Replaced 5 observable boxes (
_caseGroups,_cases,_nonEmptyCases,_caseIdsHash,_caseIdsOrderedHash) with plain variables and a single_cacheVersionobservable counter - Added two new action methods (
invalidateCaseGroups(),invalidateCaseGroupsForNewCases()) that increment the version counter from action contexts - Removed dead code:
newCaseIdsForCollectionsmap that was populated but never read
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| v3/src/models/data/collection.ts | Core refactoring: replaced observable boxes with plain variables + version counter; added invalidation actions; removed runInAction from completeCaseGroups() |
| v3/src/models/data/data-set.ts | Added invalidateCaseGroups() call in invalidateCases(); replaced dead code with invalidateCaseGroupsForNewCases() calls |
| v3/src/models/data/collection.test.ts | Updated test helper to use new invalidation API; added tests for invalidation guard scenarios |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
8b22e94 to
28cdc31
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dc7c097 to
69dc918
Compare
scytacki
left a comment
There was a problem hiding this comment.
Looks good to me.
I suspect there is some cleaner pattern, but I don't have the time to figure it out now.
scytacki
left a comment
There was a problem hiding this comment.
My last approval didn't seem to go through, trying again.
Replace observable.map cache with observable version counters (per-key and global) paired with a plain Map, so the getter never writes to an observable. This follows the same pattern as observableCachedFnFactory from PR #2377, avoiding the anti-pattern of modifying observables during computed/view evaluation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify cache-miss check (lint fix) and add note about running git commands from the repo root to avoid v3/v3 path errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…roups Replace 5 observable boxes with plain variables and a single version counter to eliminate observable writes from within a computed/view. Add invalidateCaseGroups() and invalidateCaseGroupsForNewCases() actions so that the version counter is only incremented from action contexts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When undo restores deleted cases in multiple batches (insert + append), the first batch triggers invalidateCases() but the second batch's validateCasesForNewItems() would run completeCaseGroups() with incomplete volatile state, signaling observers before data was fully rebuilt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Groups When undoing "delete unselected cases", updateCaseGroups() can return an empty newCaseIds array (because groupKeyCaseIds still has old mappings). The APPEND path condition treated [] as truthy, appending nothing instead of falling through to the REBUILD path. Check newCaseIds?.length instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The early return in validateCasesForNewItems (which skips additive processing when a full rebuild is pending) means groupKeyCaseIds may not be populated when prepareSnapshot() is called. Adding a validateCases() call in prepareSnapshot() ensures caches are current. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Cases - Collection: test that invalidateCaseGroupsForNewCases([]) falls through to the REBUILD path instead of the APPEND path (which would append nothing) - DataSet: test that addCases called while isValidCases is false (simulating undo of removeCases) correctly defers to full rebuild via validateCases() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
69dc918 to
8f98f5c
Compare
Summary
Collection.completeCaseGroups()where 5 observable boxes were written from within a computed/view viarunInAction_caseVersionobservable counter that is only incremented from action contexts (invalidateCaseGroups,invalidateCaseGroupsForNewCases)newCaseIdsForCollectionsmap inDataSet.validateCasesForNewItems()was populated but never readFixes CODAP-1117 (in part)
Test plan
🤖 Generated with Claude Code