-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Relationship Refactor (part 2): The graph should coordinate state updates #7493
Conversation
Asset Size Report for a34fcdf IE11 Builds ✅ EmberData shrank by -3.6 KB (-63.0 B compressed)Warnings
Changeset
Full Asset Analysis (IE11)
Modern Builds ☑️ EmberData shrank by -2.57 KB but the compressed size increased slighty (+132.0 B compressed)Warnings
Changeset
Full Asset Analysis (Modern)
Modern Builds (No Rollup) ☑️ EmberData shrank by -370.0 B but the compressed size increased slighty (+491.0 B compressed)Warnings
Changeset
Full Asset Analysis (Modern)
|
Performance Report for a34fcdf Scenario - materialization: ✅ Performance improved
Scenario - unload: ✅ Performance improved
Scenario - destroy: ✅ Performance improved
Scenario - add-children: ✅ Performance improved
Scenario - unused-relationships: ✅ Performance improved
|
7bd2e41
to
caffec6
Compare
0683d69
to
72e8068
Compare
84a8e30
to
fb7f032
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really nice and easy to follow. When I get to work in this area, I am sure it will all be easy to navigate and understand. Not able to comment on edge cases or potential regressions other than relying on the test suite. So you get an A+ from me!
this._internalModel.rollbackAttributes(); | ||
this.store._backburner.join(() => { | ||
this._internalModel.rollbackAttributes(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What did you see here (and in other spots) to add the join
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed we were using a join around the notify
and push
schedules, which meant these things were being called without an existing join. I worked through all the possible entry points to that flush and found which ones didn't have a join wrapper already and added them.
Moving the join up means that a lot of scenarios that were creating a flush-per-schedule now create only one flush, which helps us avoid a lot more work. This had the most noticeable effect on teardown/unload.
syncRelationships is used by the UI to grab updates from the graph | ||
and update the ManyArrays. | ||
|
||
We may be able to remove this once the new relationship layer is | ||
complete. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to the other question, what will allow it's removal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our scheduler right now does three things (which is why there are three queues)
- it batches payloads that have been pushed for a single flush, thereby allowing us to order the pushes by type (more efficient to push hasMany first. Removing this batching regressed the update scenario by 500%). It's unclear how we'd do this without some form of run loop concept, however we could probably make a simpler queue thing and drop our need for backburner if this was all that was left.
- it batches (and minimizes) updates to hasMany local state in a second pass, this allows us to update the local state with those changes only once instead of potentially many times. This optimization would go away if we were to compute localState lazily on access.
- it notifies the UI layer only once all state has settled (and minimizes those notifications to only one per relationship). We can possibly do away with this once we no longer support sync-observers if state is also lazily calculated.
assert.equal(comment.get('post'), post); | ||
assert.equal(post.get('bestComment'), comment); | ||
assert.strictEqual(post2.get('bestComment'), null); | ||
assert.ok(comment.get('post') === post, 'comment post is set correctly'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some cleanup here
@@ -1046,11 +1046,7 @@ module('integration/store - deleteRecord', function (hooks) { | |||
|
|||
assert.ok(store.hasRecordForId('person', '1'), 'expected the record to be in the store'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an intentional removal
Basic premise here is that the individual edges can't optimize updating their inverses, state, or notifying the UI efficiently while the graph, acting as a coordinator, can.
The existing explosion of "remove" and "add" spaghetti (roughly 12 different methods for removing a record from one side last I counted) was primarily due to attempting to prevent "cycling" (an update to one side updating it's inverse which then sends the same updates back to the originating side, potentially bouncing multiple times). These efforts were mostly in vain and we often cycle multiple times even in a first load scenario.
When this PR completes, we should be left in a state of updating the various edges while only visiting each once per relationship payload received (note: a json-api payload will typically contain multiple relationship payloads for the same relationship, so this does not yet do any work to avoid that double pass).