Summary
I suspect I am encountering a race condition when bootstrapping my Vaadin Flow app over a throttled network connection, and it results in a catastrophic failure of the client-side JavaScript
Details
- I have a Vaadin Flow (v24.3.12) app that is using server push (via web sockets)
- On the server-side I have asynchronous tasks that only get invoked from within
onAttach()
methods within Components - I am careful to ensure that asynchronous tasks are using
UI.access()
for making changes to UI state - Using Chrome Dev Tools I am setting the network throttling to 128kb/s
- Running without ‘hot deploy’ (i.e. without a dev server) I do a ‘Hard Reload’ of the browser page to force a full bootstrap of the Vaadin client JavaScript
- I see the following network activity,
- <various .js resources>
generated-flow-imports-DtSjheap.js
(6.4MB) gets downloadedFlowClient-BZ2ixoyw.js
(233kB) gets downloadedapp/?v-r=uidl&v-uidl=1
request is sent (I assume this is the inital request for server-side UI state)push?v-r=push&v-uiId=1&v-pushId=<some hex>
(web socket)
- Looking at the messages being sent over the web-socket, I see a large message that DOES NOT appear without a throttled connection. When it does appear I always have a catastrophic failure in
FlowClient-BZ2ixoyw.js
(which is minified, so I can’t really tell why) - When my app has low volumes of data being displayed the error scenario does not occur
- I have have been unable to re-produce with an adapted
starter-app
, but I suspect this is because there is insufficient UI state to make the uidl messages sufficiently large
Thoughts
My best theory is that the inital request for the UI state gets into a race with an async server-side task. If the async task gets to do a server push early enough it will result in complete server-side state being sent over the web-socket, otherwise the initial request ‘wins’ and it will have already sent the server-side state (so web-socket won’t). But I don’t know if this is even plausible.
Questions
- Can anyone confirm/debunk the possibility of the above theory? It seems suprising that an async task using correct UI locking would attempt to send any UI state before the initial state had already been sent (or at least processed).
- Is there any event that I can listen for to know when the intial UI state has been sent/processed. In which case I can wait for this event before starting async tasks.
- Is there a way to run without minified client-side code so that I can see what the error on the client-side is? Not actually sure how useful this will be.
- Any advice as to how to debug this further or even how to resolve it?
Appreciate any assistance, thank you.