Repository navigation
fix(shared-state): keep initial snapshots local - #454
Merged
Merged
Conversation
|
@SaKaNa-Y is attempting to deploy a commit to the NuxtLabs Team on Vercel. A member of the Team first needs to authorize it. |
|
👁️🗨️ Review this pull request with grouped, summarized diffs at: raw result💭 analyzed by {
"headSha": "bea3b054102507369c8e233ba2a3bccf22fdaaff",
"result": {
"overallSummary": "Fixes a race where an RPC client's initial shared-state snapshot read could resolve after a newer update/local write/delete and overwrite it, which could drop a service advertisement on the node side. The client now tags the initial read with its own sync ID, excludes it from outgoing writes, and only applies it if nothing changed in the meantime. An unrelated UnoCSS config fix pulled in from `main` is also included.",
"groups": [
{
"key": "shared-state-fix",
"label": "Keep initial snapshots local",
"summary": "Gives each initial shared-state snapshot read its own sync ID, excludes it from outgoing writes, tracks updates/deletes that happen while the read is pending, and stops listening once the read resolves — preventing a stale snapshot from overwriting a newer local write or clobbering a service advertisement on the node side.",
"category": "core",
"filePaths": [
"packages/devframe/src/client/rpc-shared-state.ts"
],
"critical": true,
"lineNotes": [
{
"path": "packages/devframe/src/client/rpc-shared-state.ts",
"side": "additions",
"line": 117,
"text": "Core fix: the resolved snapshot is only applied if the state wasn't replaced/deleted and no update happened while the read was pending, otherwise the stale value would silently win."
}
]
},
{
"key": "shared-state-tests",
"label": "Shared-state snapshot tests",
"summary": "Adds coverage for the new initial-snapshot handling: no write-back, updates/local writes/undo during a pending read, unchanged mutations, writes triggered from a snapshot listener, and deletion before the snapshot resolves.",
"category": "tests",
"filePaths": [
"packages/devframe/src/client/rpc-shared-state.test.ts"
]
},
{
"key": "unocss-config-fix",
"label": "Fix UnoCSS content exclude",
"summary": "Unrelated fix (from a merged branch) restoring UnoCSS's default pipeline exclude, which `mergeConfigs` was otherwise wiping, causing no utilities to be extracted from app sources under UnoCSS 66.11.",
"category": "build",
"filePaths": [
"design/uno.config.ts"
],
"fileNotes": [
{
"path": "design/uno.config.ts",
"text": "Merge artifact from `main`, unrelated to the shared-state fix but included in this PR's diff."
}
]
}
],
"schemaVersion": 1,
"source": "llm",
"generatedAt": "2026-11-01T13:17:35.651Z",
"model": "vercel-ai-gateway/anthropic/claude-sonnet-5",
"locale": "en"
}
} |
SaKaNa-Y
marked this pull request as draft
October 21, 2026 13:36
Track updates while the initial snapshot is pending. Restoring the original object after a local edit must not make a stale snapshot current again. Add an undo regression and retain initial synchronization after unchanged mutations. All required checks and the WebSocket/SSE service-discovery workflows pass.
SaKaNa-Y
marked this pull request as ready for review
November 1, 2026 05:04
antfu
approved these changes
Nov 1, 2026
`mergeConfigs` leaves `content.pipeline.exclude` as `[]`. UnoCSS 66.11 builds its exclude filter with an empty include list, so an empty exclude matches every module and no utilities come from app sources. The a11y panel lost `overflow-y-auto`, which broke the scroll e2e test. Restate the default exclude in the shared design config so the merged list is never empty. Co-Authored-By: Claude Opus 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
When a wire service is installed while the RPC client reads its initial shared-state snapshot, the client can send the old snapshot back to the node side. This removes the service advertisement even though direct RPC calls still work. New connections then also fail to discover the installed service.
Give the initial snapshot its own sync ID and exclude that ID from outgoing writes. Track updates while the read is pending and ignore its result if the state changed or was deleted. This also preserves a local undo that restores the original object. Remove the temporary update listener when the read finishes. Local writes, including writes triggered by a snapshot listener, still reach the node side.
This PR and #422 are independent fixes with no dependency on each other. This PR is based on
mainand does not include changes from #422. It fixes initial snapshot reads; #422 fixes echoes from received broadcasts and patches.Evidence
pnpm lint,pnpm knip,pnpm typecheck, andpnpm buildpass.pnpm test --run: 157 test files pass; 1762 tests pass and 13 are skipped.Merge Danger
Door: two-way. No wire-format or public API changes.
Blast Radius: shared-state. The change affects initial reads with an
initialValue; later local writes retain their existing behavior.