Repository navigation
Conversation
A publication could be lost or applied out of order while an instance was still hydrating: - a delta arriving before the class definition threw on `dataclass_containers` and was dropped; - a delta arriving while nested refs were still being fetched wrote to a ref that did not exist yet; - a delta arriving during the first `state.get` was matched to the pending fetch and never applied; - an older async handler awaiting a child fetch could finish after a newer one and overwrite its value. Client: every publication now waits for the instance's whole `fetchState` (nested children included) and runs through a per-instance promise queue; a failed update settles only its own entry. Server: snapshots and deltas carry a per-instance revision, so a replayed delta that a newer snapshot already contains is dropped instead of rolling the value back. Revisions are keyed by the model's `_id`, so models need not be hashable and equal-but-distinct models keep separate counters. Servers without revisions keep the previous behaviour. Adds tests/test_protocol_revisions.py and vue-components/tests/ publication-order.cjs (`npm test`). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Superseeded by #15, which includes these changes |
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 2.2.1 the Vue
DataclassManagercan lose a publication, or apply it out of order, while an instance is still hydrating. There are four windows:fetchStatefillsdataStates[id]beforedefinition.getresolves. A publication that arrives in between treats the entry as ready.isDataClassthen dereferences the missing definition and throws ondataclass_containers, and the delta is lost.fetchStateawaits each child container before it builds the next field's ref. A publication during that wait writes to a ref that doesn't exist yet.state.getis still out. The subscription takes theif (!dataStates[id]) { await fetchState(id); return; }path.fetchStatereturns the already-pending promise, and the handler exits without applying the publication. If the snapshot was taken before the delta, the newer value is gone.Fix
Client (
vue-components/src/core.js):fetchState, including its nested child handlers.fetchStaterejects on RPC failure instead of leaving a promise pending forever.Server (
protocol_v2.py):revision. The client uses it to drop a replayed delta that a newer snapshot already contains, rather than rolling the value back._id, withweakref.finalizecleanup, not by the instance. So models don't need to be hashable (a subclass with__eq__and no__hash__keeps working), and two equal-but-distinct models keep separate counters.Tests
tests/test_protocol_revisions.py: revision numbering, snapshot/payload immutability, weak lifetime, unhashable models, and equal-but-distinct models.vue-components/tests/publication-order.cjs(newnpm testscript): runs the realcore.jsagainst a small fake wslink session with real Vue refs, so every race above is reproduced deterministically by holding RPC replies.core.js(DATACLASS_CORE=/path/to/old/core.js npm test), 10 of the 12 client tests fail. The two that pass cover behaviour the patch deliberately keeps.pre-commit runpasses on the changed files.Small reproduction
A container that swaps in a new child and then changes a scalar, in a burst that starts as soon as the client connects:
python demo.py --server --port 8080, then load the page a few times. Measured in Chromium, 12 loads each (6 with no added latency, 6 with 40 ms):Cannot read properties of undefined (reading 'dataclass_containers')deep_reactive)In this demo the final rendered value is correct in both cases. The test file covers the ordering cases, where 2.2.1 ends on the wrong value.
Not in scope
{id, state: null}).Happy to adjust the approach, or split the client and server parts.
🤖 Generated with Claude Code