New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bug in SharedTree factory proxy hydration #18245
Conversation
experimental/dds/tree2/src/test/feature-libraries/editable-tree-2/list.spec.ts
Show resolved
Hide resolved
experimental/dds/tree2/src/feature-libraries/editable-tree-2/proxies/proxies.ts
Outdated
Show resolved
Hide resolved
⯅ @fluid-example/bundle-size-tests: +729 Bytes
Baseline commit: 4505170 |
experimental/dds/tree2/src/test/feature-libraries/editable-tree-2/objectFactory.spec.ts
Outdated
Show resolved
Hide resolved
experimental/dds/tree2/src/test/feature-libraries/editable-tree-2/proxies.spec.ts
Outdated
Show resolved
Hide resolved
|
@tyler-cai-microsoft from the description, sounds like this is the issue you repro'd? |
The error thrown is is "Cannot associate an edit node with multiple targets". |
Tyler's repro is here if you'd like to try it against your change: https://github.com/microsoft/FluidFramework/pull/18232/files#diff-c97fa3e4c7401e9a6829502d0aad7df0c10e5289fd73315465254f0c429be6d0R12 |
experimental/dds/tree2/src/feature-libraries/editable-tree-2/editableTreeTypes.ts
Outdated
Show resolved
Hide resolved
experimental/dds/tree2/src/feature-libraries/editable-tree-2/editableTreeTypes.ts
Show resolved
Hide resolved
experimental/dds/tree2/src/test/feature-libraries/editable-tree-2/editableTree.events.spec.ts
Show resolved
Hide resolved
experimental/dds/tree2/src/test/feature-libraries/editable-tree-2/editableTree.events.spec.ts
Outdated
Show resolved
Hide resolved
Thanks for the repro! Yea, that is the exact bug this PR is fixing. I confirmed that that test passes with the code in this PR. |
Description
There currently exists a bug during proxy hydration. In the proxy API, proxies in the input tree are immediately hydrated after inserting content into the tree, however, tree-change events are nonetheless fired after insertion but before hydration occurs. If any of these tree events incur a read of the tree location where a proxy is pending hydration, then a new proxy will be created before hydration of the existing proxy occurs. When hydration of that proxy does occur soon after, it will throw an error because it is illegal to map two proxies to the same input node.
Fixing this requires careful consideration of the event sequencing. This PR implements the following solution. A new anchor event is introduced that fires immediately after content is inserted (and before any other events are fired). This event,
childrenChangedis a mirror of the existingchildrenChangingevent; it happens just after the edit to the forest rather than just before. An event in the editable tree layer is built on top of this. However, it is problematic if anyone subscribes to such an event. It can introduce the same problem as exists now: if the event listener reads the tree in the wrong place during an insert, proxy hydration will fail for the same reason. So, the event registration is not exposed publicly alongside other events onTreeNodebut is instead keyed by an internal (un-exported) symbol (onNextChange). It is further tailored to the scenario at hand; the event can only have one listener at a time and it automatically deregisters itself after firing the first time. This makes it suitable for proxy hydration and not much more, so as to discourage any more internal widespread use. Anytime that content is inserted into the tree by the proxy API, this event is subscribed to just before the insertion, and proxy hydration occurs when the event fires. Proxies are thus hydrated before any other events can examine to the tree state after the change.There are other ways to solve this problem. For example, if inserted content could be identified with some token (e.g. a node key a.k.a. a node identifier), then the proxies could be keyed off of the token rather than the edit node, and be cached in a map even before insertion. Such a token does not currently exist but may in the future, at which time we can revisit this.
This PR also does some minor test and documentation cleanup.