fix(user-state): upsert sys_user_preference by (user_id, key)#2116
Merged
Conversation
The ObjectStack-backed UserDataAdapter (ui.recent / ui.favorites) tripped the UNIQUE(user_id, key) constraint on sys_user_preference: every other navigation logged "Insert operation failed" server-side. A fresh `recent` adapter is created whenever dataSource/user changes (UserStateBridge), so cachedRowId starts null. Rapid navigations fire overlapping debounced save() flushes that both findExisting()->null-> create() — the first insert wins, the second hits the constraint. And when the row already existed but wasn't found, create() threw with no recovery. - Extract an upsert() helper; on create() failure (UNIQUE violation), re-find and update in place — a real (user_id, key) upsert. - Serialize overlapping save() calls via a saveChain so the second save sees the cachedRowId the first set and updates instead of inserting. - save() still swallows errors (provider falls back to localStorage). Tests: + insert-failure recovery, + concurrent-save serialization (13 pass). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
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.
Problem
In cloud local dev, navigating logs a server-side error on every other navigation:
key='ui.recent', and(user_id, key)is unique. It doesn't break rendering — just floods the logs.Root cause
createObjectStackUserStateAdapter().save()(theui.recent/ui.favoritespersistence adapter) already did find-then-insert, but two gaps let the constraint trip:recentadapter is created wheneverdataSource/user changes (UserStateBridge), socachedRowIdstartsnull. Rapid navigations fire overlapping debouncedsave()flushes that bothfindExisting()→null→create(). The first insert wins; the second hits the UNIQUE constraint.create()threw with no fallback to update.Fix
upsert()helper. Oncreate()failure (UNIQUE violation), re-find and update in place — a true(user_id, key)upsert.save()calls via asaveChainso the second save sees thecachedRowIdthe first one set and updates instead of inserting.save()still swallows errors (provider falls back to localStorage).Tests
packages/data-objectstack/src/userState.test.ts— added:All 13 tests pass.
🤖 Generated with Claude Code