Handling fast progress bar updates with server push

We are using the progress bar component at various places to indicate the progress of background jobs.
For this we are using server push and the UI.access() {} which works fine.

But we notice a “problem” when the background task sends the progressbar updates very fast via push.
In that case the backgroud thread for example is finished after 5-10 seconds, but the UI takes then 2-3 minutes to “display” every progress bar update sent from the backend.

We have added a logic in some places, that only every 50th or 100th progress step is sent to the client.
But sometimes we would need to see smaller steps too.

I think the way to go would be to somehow not flood the progress bar with progress messages, but not depending on the absolute numbers, but rather some rate limiting (Making sure the last updates also go to the UI)

Has anyone also stumble over this behaviour and has perhaps some code to solve the problem?

Could you please provide a small example of the problem?

I have a dialog which shows the progress with a progress bar and a div for the text representation of the progress.

This dialog has this code (simplified) to update the progress bar and progress text

public void notifyProgress(long totalRows, long currentRow, String message) {
if (currentUI != null && currentUI.isAttached()) {
currentUI.access(()
→ {
progressDisplay.setText(message);
progressBar.setValue(calc of %);
}
);
}
}

The code calling the notifyProgress looks like this:

In a background thread:
for (I=0; i < 1000000; i++) {
progressDialog.notifyProgress(1000000, i, "Updating row "+i);
// do more of less heavy work
}

When the “heavy work” takes 2-3 or more seconds, no problem, everything is running fine.
But if the heavy work isn’t heavy, and only takes 0.01ms for example, then the for loop is finished after 5-10 seconds.
But the UI keeps updating all 1000000 rogressbar updates and also all text updates of the text part.

In short all 1000000 UI updates are sent to the client and processed there, which then takes for example 5 minutes or more

I would probably store a timestamp for last push, and calculate how many ms have passed since then.
If 500ms have passed OR 100% reached, I would push, otherwise not.

so would be something like this:

long lastPush = System.currentTimeMillis();
for (int i =0; i < 1000000; i++) {
    // do more of less heavy work

    long now = System.currentTimeMillis();
    if (now - lastPush > 500) {
        System.out.println("Progress: " + i);
        lastPush = now;
    } 
}

Yes, I think we have to do something like this, but with yet one more background thread, otherwise the “last” progress will not be pushed to the client