vaadin / framework

Vaadin 6, 7, 8 is a Java framework for modern Java web applications.
http://vaadin.com/
Other
1.77k stars 729 forks source link

Push freezes UI when preserving UI on refresh. #12577

Closed lennartfricke closed 1 year ago

lennartfricke commented 1 year ago

Using the attached example code, refreshing the browser leads to infrequent freezes of the UI. The progress bar is shown and does not vanish.

package vaadin8_push;

import java.time.ZonedDateTime;

import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.annotations.Push;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.communication.PushMode;
import com.vaadin.shared.ui.ui.Transport;
import com.vaadin.ui.Button;
import com.vaadin.ui.UI;

@Push(transport = Transport.LONG_POLLING, value = PushMode.MANUAL)
@PreserveOnRefresh
public class TestUI extends UI {

    private Thread bt;

    @Override
    protected void init(VaadinRequest request) {
        var time = new Button("Test");

        bt = new Thread(() -> {
            try {
                while (true) {
                    this.access(() -> {
                        time.setCaption(ZonedDateTime.now().toString());
                        this.push();
                    });
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        bt.setName("time-" + request.getWrappedSession().getId());
        bt.start();

        this.setContent(time);
    }

    @Override
    public void detach() {
        super.detach();
        bt.interrupt();
    }

}

The browser log shows:

Mon Jan 30 12:17:49 GMT+100 2023 com.vaadin.client.communication.MessageHandler
WARNING: Gave up waiting for message 51 from the server
Mon Jan 30 12:17:49 GMT+100 2023 com.vaadin.client.communication.MessageSender
INFO: Resynchronize from server requested

but no request is send, which can be seen from the network log of the browser.

Decreasing the sleep time makes the issue appear more often. But increasing it to does not make it vanish completely, so that I think that the browser is able to handle all responses in time.

We also experience infrequent freezes in our production code, even without refresh. But in that case there is proxy in between that might interrupt push long polling requests with gateway timeout responses, which might be related to the freezes.

I was hoping that the client side code is able to resynchronize when messages get lost.

Until this is fixed we need to revert to polling, which breaks session timeouts and automatic logout unfortunately.

Probably related: #7719

I can also upload the full source code for reference if you like.

Ansku commented 1 year ago

On a quick glance this override to the UI class seems to help:

    @Override
    public void doRefresh(VaadinRequest request) {
        PushConnection pushConnection = getPushConnection();
        if (pushConnection instanceof AtmospherePushConnection
                && pushConnection.isConnected()) {
            pushConnection.disconnect();
        }
        super.doRefresh(request);
    }

This method is called when the UI is reinitialized, and closing the old connection here already (rather than later, when the new connection is ready to be registered) stops the Push from attempting to send more requests through the old connection and increasing the counter with every call while the new connection is still being initialized. I haven't run this solution through our validation builds yet, but at least my test project seems to behave better with it.