-
Notifications
You must be signed in to change notification settings - Fork 169
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
Node bindings should be applied only after all state nodes have been updated #1051
Comments
I just realized that we've all been looking at this problem from the wrong direction. The original problem is that actions are performed eagerly when some part of the state tree is being updated instead of deferring the actions until the entire tree has been updated. This is easily done either through using |
See https://reviewable.io/reviews/vaadin/hummingbird/1052 how it could be fixed. |
@Legioth Will it really solve an issue ? |
I don't think there are any cases where it would matter in which order individual changes are processed, as long as the processing is done only after all state tree changes have been applied. |
Yes, you are right. The order should not matter. Except one aspect. MapProperty overrideProperty = modelNode
.getMap(NodeFeatures.TEMPLATE_OVERRIDES)
.getProperty(String.valueOf(templateNode.getId()));
if (overrideProperty.hasValue()) { So it assumes that there is always TEMPLATE_OVERRIDES feature for the node. In this specific case it's OK. |
I would suggest send all features (+their types) as a part of "attach" message and initialize them immidiately BEFORE (as it's done with attach messages now) any other actions in addition to deferred processing . |
Yes, it assumes that the node has been updated, but not that any specific change events have been run for that node. Why not also make this binder logic run deferred? In that way everything could work in the same way without any special case processing. The only question then is whether we could do something to let anyone discover when they've forgot to do something deferredly. |
Actually we already has this kind of code that I'm referring to : private JavaScriptObject createServerProxy(StateNode templateStateNode) {
assert templateStateNode.hasFeature(NodeFeatures.TEMPLATE);
JavaScriptObject proxy = JavaScriptObject.createObject();
if (templateStateNode
.hasFeature(NodeFeatures.TEMPLATE_EVENT_HANDLER_NAMES)) {
NodeList list = templateStateNode
.getList(NodeFeatures.TEMPLATE_EVENT_HANDLER_NAMES);
for (int i = 0; i < list.length(); i++) {
attachServerProxyMethod(proxy, templateStateNode,
list.get(i).toString());
}
}
return proxy;
} If for some reason node has no yet TEMPLATE_EVENT_HANDLER_NAMES then it will not be executed and will not be executed in the future. But with my suggestion we should not assume anymore that some feature has "static" values ( that never cahnges). If we initialize the feature in the very beginning then its values will be set later on at any time. So any read should use "bind" method. |
What do you mean ?
to be deferred ? Does Reactive handle automatically this ? |
Adjustments to the order of applying changes from the server will not be enough when we also add support for changing the model from JavaScript in the browser. This means that we cannot rely on reordering, but must instead make sure all change listeners can deal with changes happening in any order.
After the tree has been updated, we are always running We want to reduce the risk of accidentally doing any processing eagerly since basically all processing we're doing might directly or indirectly depend on other parts of the tree. We cannot directly change the eager events to be fired lazily since some inner workings of What we can do is to create an overload of each of the three addXyzListener methods that takes an additional |
Sorry, I'm a bit lost. You are describing already some solution. Solution for the initial issue or solution for some suggestions mentioned here ? |
Solution for the root cause, which should also fix all the specific issues. |
OK.......
And still, what to do with this code: if (templateStateNode
.hasFeature(NodeFeatures.TEMPLATE_EVENT_HANDLER_NAMES)) { ? |
By starting at the root cause: the entire chain of processing that eventually ends up calling The solution would be to make sure that entire chain of processing is run through My suggestion for making state node events fire lazily by default would significantly reduce the risk of causing this kind of hard-to-trace issues in the future, even when state node changes can also be triggered from other sources than a list of changes arriving from the server. |
Adding |
Yes, agreed.
Yes, agreed.
These I don't understand. I believe you are talking about listeners in 3 implementations of And I still don't see how it helps to avoid getting false for the call if (templateStateNode
.hasFeature(NodeFeatures.TEMPLATE_EVENT_HANDLER_NAMES)) { in Anyway, since it's my last day before vacation I won't proceed with this today. |
Oh, you're right. We could probably just make all three addXyzListener methods invoke the listener deferredly and then go through all users to remove the explicit
|
Right. This is a bad example. But what if current code MapProperty overrideProperty = modelNode
.getMap(NodeFeatures.TEMPLATE_OVERRIDES)
.getProperty(String.valueOf(templateNode.getId()));
if (overrideProperty.hasValue()) { is rewritten like this : if ( modelNode.hasFeature(NodeFeatures.TEMPLATE_OVERRIDES)){
MapProperty overrideProperty = modelNode
.getMap(NodeFeatures.TEMPLATE_OVERRIDES)
.getProperty(String.valueOf(templateNode.getId()));
if (overrideProperty.hasValue()) {
.....
} |
I don't understand your point.
The logic that deals with override nodes should be written in a way that lets it detect whenever a new template override is added, since the first one might be added in any round trip. Wrapping the code that adds the listener in an |
Yes.
Should be , yes. |
We will if there's a test for it, or if a demo somewhere uses it. The conclusion is probably that we might want to think about how to prevent accidentally using |
There is an issue #1050 which is the main reason for this issue.
The fix for the issue is a custom way to struggle against the order for a node with TemplateOverridesMap feature and the node which it refer to (the node with OverrideElementData feature).
The fix works for it but it means that in each similar situation one has to remember about this kind of issues and be aware of the order of message processing.
Normally the message processing should care about the order and process some nodes before others.
Here is the example of messages :
Node 9 refers to node 75 which has been attached (because attach events are processed first) but it has no yet feature 19 (OverrideElementData feature).
So the Binder doesn't know how to handle it.
This situation may be generic enough and changes for node 9 should not be processed before changes for node 75.
So some ordering in message processing might be required.
The text was updated successfully, but these errors were encountered: