public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout
@ 2024-03-18 13:44 Dominik Csapak
  2024-03-18 15:50 ` Thomas Lamprecht
  0 siblings, 1 reply; 5+ messages in thread
From: Dominik Csapak @ 2024-03-18 13:44 UTC (permalink / raw)
  To: pve-devel

since some time (not sure when exactly), the 'load()' method of the edit
window did not correctly mask the window anymore

the reason seems to be that the API2Request tries to mask the component
before it's rendered, and that did never work correctly judging from the
existing comment.

Instead of simply calling `setLoading`, test if the component is
rendered, and if not, mask it after it has finished it's layout.

Since we cannot guarantee that the 'afterlayout' event is triggered
before the api call response handler, add a unique id marker to the
waitMsgTarget that is delted when the loading is done, and only trigger
the masking if this marker is still there. (thankfully javascript is
single threaded so this should not end up being a data race)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
sending as RFC because i'm unsure if we accidentally broke the masking
somewhere along the way. AFAICS from the current code, this never could have
worked properly? anyway, i'll be looking into that sometimes soon, and
this patch should be correct anyway...

 src/Utils.js | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/Utils.js b/src/Utils.js
index ff7c1a7..b5e12f3 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -458,6 +458,7 @@ utilities: {
 	    newopts.url = '/api2/extjs' + newopts.url;
 	}
 	delete newopts.callback;
+	let loadingId = `loading${++Ext.idSeed}`;
 
 	let createWrapper = function(successFn, callbackFn, failureFn) {
 	    Ext.apply(newopts, {
@@ -467,6 +468,7 @@ utilities: {
 			    options.waitMsgTarget.setMasked(false);
 			} else {
 			    options.waitMsgTarget.setLoading(false);
+			    delete options.waitMsgTarget[loadingId];
 			}
 		    }
 		    let result = Ext.decode(response.responseText);
@@ -489,6 +491,7 @@ utilities: {
 			    options.waitMsgTarget.setMasked(false);
 			} else {
 			    options.waitMsgTarget.setLoading(false);
+			    delete options.waitMsgTarget[loadingId];
 			}
 		    }
 		    response.result = {};
@@ -518,9 +521,15 @@ utilities: {
 	if (target) {
 	    if (Proxmox.Utils.toolkit === 'touch') {
 		target.setMasked({ xtype: 'loadmask', message: newopts.waitMsg });
-	    } else {
-		// Note: ExtJS bug - this does not work when component is not rendered
+	    } else if (target.rendered) {
 		target.setLoading(newopts.waitMsg);
+	    } else {
+		target[loadingId] = true;
+		target.on('afterlayout', function() {
+		    if (target[loadingId]) {
+			target.setLoading(newopts.waitMsg);
+		    }
+		}, target, { single: true });
 	    }
 	}
 	Ext.Ajax.request(newopts);
-- 
2.39.2





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout
  2024-03-18 13:44 [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout Dominik Csapak
@ 2024-03-18 15:50 ` Thomas Lamprecht
  2024-03-19  7:44   ` Dominik Csapak
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Lamprecht @ 2024-03-18 15:50 UTC (permalink / raw)
  To: Proxmox VE development discussion, Dominik Csapak

On 18/03/2024 14:44, Dominik Csapak wrote:
> since some time (not sure when exactly), the 'load()' method of the edit
> window did not correctly mask the window anymore
> 
> the reason seems to be that the API2Request tries to mask the component
> before it's rendered, and that did never work correctly judging from the
> existing comment.
> 
> Instead of simply calling `setLoading`, test if the component is
> rendered, and if not, mask it after it has finished it's layout.
> 
> Since we cannot guarantee that the 'afterlayout' event is triggered
> before the api call response handler, add a unique id marker to the
> waitMsgTarget that is delted when the loading is done, and only trigger

s/delted/deleted/

And why do we need setting a unique ID here and not just a flag?
Can a second load be triggered before the first one finished?

> the masking if this marker is still there. (thankfully javascript is
> single threaded so this should not end up being a data race)

Note that async could cause data races also in single-threaded
code, but as we do not use that here and no yield point exist
that doesn't matter here – just mentioning it because the statement
would suggest that one could not have code that is susceptible to
such a race at all in JavaScript, which is not true.

> 
> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
> ---
> sending as RFC because i'm unsure if we accidentally broke the masking
> somewhere along the way. AFAICS from the current code, this never could have
> worked properly? anyway, i'll be looking into that sometimes soon, and
> this patch should be correct anyway...

it surely did sometimes in the past, maybe ExtJS 7?




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout
  2024-03-18 15:50 ` Thomas Lamprecht
@ 2024-03-19  7:44   ` Dominik Csapak
  2024-03-19  8:09     ` Dominik Csapak
  2024-03-19  8:21     ` Thomas Lamprecht
  0 siblings, 2 replies; 5+ messages in thread
From: Dominik Csapak @ 2024-03-19  7:44 UTC (permalink / raw)
  To: Thomas Lamprecht, Proxmox VE development discussion

On 3/18/24 16:50, Thomas Lamprecht wrote:
> On 18/03/2024 14:44, Dominik Csapak wrote:
>> since some time (not sure when exactly), the 'load()' method of the edit
>> window did not correctly mask the window anymore
>>
>> the reason seems to be that the API2Request tries to mask the component
>> before it's rendered, and that did never work correctly judging from the
>> existing comment.
>>
>> Instead of simply calling `setLoading`, test if the component is
>> rendered, and if not, mask it after it has finished it's layout.
>>
>> Since we cannot guarantee that the 'afterlayout' event is triggered
>> before the api call response handler, add a unique id marker to the
>> waitMsgTarget that is delted when the loading is done, and only trigger
> 
> s/delted/deleted/
> 
> And why do we need setting a unique ID here and not just a flag?
> Can a second load be triggered before the first one finished?

yes, my thought here (that i forgot to mention) was that when
we have multiple API2Requests their start/finish and the 'afterlayout'
may overlap so i only wanted to activate the mask when this load
was not finished

thinking about it a bit more though, i think what would be better here
is a ref counting of running api2 requests on that waitMsgTarget
and only unmask when the count reaches zero... I'll send a v2 for that

> 
>> the masking if this marker is still there. (thankfully javascript is
>> single threaded so this should not end up being a data race)
> 
> Note that async could cause data races also in single-threaded
> code, but as we do not use that here and no yield point exist
> that doesn't matter here – just mentioning it because the statement
> would suggest that one could not have code that is susceptible to
> such a race at all in JavaScript, which is not true.

true, but those can only happen (as you mentioned) at yield points (await)
and since most of our code is non-async i did not mention it here, but
yeah one additional sentence about it being non async is probably warranted

> 
>>
>> Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
>> ---
>> sending as RFC because i'm unsure if we accidentally broke the masking
>> somewhere along the way. AFAICS from the current code, this never could have
>> worked properly? anyway, i'll be looking into that sometimes soon, and
>> this patch should be correct anyway...
> 
> it surely did sometimes in the past, maybe ExtJS 7?


yeah maybe, I'll see if i can find out when it still worked and why..
could also be general browser behavior change though




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout
  2024-03-19  7:44   ` Dominik Csapak
@ 2024-03-19  8:09     ` Dominik Csapak
  2024-03-19  8:21     ` Thomas Lamprecht
  1 sibling, 0 replies; 5+ messages in thread
From: Dominik Csapak @ 2024-03-19  8:09 UTC (permalink / raw)
  To: Thomas Lamprecht, Proxmox VE development discussion


>>> sending as RFC because i'm unsure if we accidentally broke the masking
>>> somewhere along the way. AFAICS from the current code, this never could have
>>> worked properly? anyway, i'll be looking into that sometimes soon, and
>>> this patch should be correct anyway...
>>
>> it surely did sometimes in the past, maybe ExtJS 7?
> 
> 
> yeah maybe, I'll see if i can find out when it still worked and why..
> could also be general browser behavior change though
> 

so tested back to pve 5 and the behaviour is still the same on chrome/firefox.
my guess is simply either changed browser behaviour or we missed that for much
longer than i thought...




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout
  2024-03-19  7:44   ` Dominik Csapak
  2024-03-19  8:09     ` Dominik Csapak
@ 2024-03-19  8:21     ` Thomas Lamprecht
  1 sibling, 0 replies; 5+ messages in thread
From: Thomas Lamprecht @ 2024-03-19  8:21 UTC (permalink / raw)
  To: Dominik Csapak, Proxmox VE development discussion

On 19/03/2024 08:44, Dominik Csapak wrote:
> thinking about it a bit more though, i think what would be better here
> is a ref counting of running api2 requests on that waitMsgTarget
> and only unmask when the count reaches zero... I'll send a v2 for that

fine by me, both have some coupling in how the component is doing
loading and could theoretically break and possibly have a tiny
chance that they result in flickering when having the UI open on
a localhost and the first load finishes before the second one
started.

In anyway, this would be still a improvement over the current
situation, so fine by me.


On 19/03/2024 08:44, Dominik Csapak wrote:
> On 3/18/24 16:50, Thomas Lamprecht wrote:
>> On 18/03/2024 14:44, Dominik Csapak wrote:
>>> the masking if this marker is still there. (thankfully javascript is
>>> single threaded so this should not end up being a data race)
>>
>> Note that async could cause data races also in single-threaded
>> code, but as we do not use that here and no yield point exist
>> that doesn't matter here – just mentioning it because the statement
>> would suggest that one could not have code that is susceptible to
>> such a race at all in JavaScript, which is not true.
> 
> true, but those can only happen (as you mentioned) at yield points (await)
> and since most of our code is non-async i did not mention it here, but
> yeah one additional sentence about it being non async is probably warranted

yeah, as said, just your blanket statement is wrong in the general
sense, so I'd either drop it or adapt it to "as we're in
synchronous JS code there can be no data-race" would be less
contentious




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-03-19  8:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-18 13:44 [pve-devel] [RFC PATCH widget-toolkit] utils: API2Request: defer masking after layout Dominik Csapak
2024-03-18 15:50 ` Thomas Lamprecht
2024-03-19  7:44   ` Dominik Csapak
2024-03-19  8:09     ` Dominik Csapak
2024-03-19  8:21     ` Thomas Lamprecht

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal