Skip to content
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

Turbo 8 refresh debounce in frontend #1093

Closed
edwinv opened this issue Dec 1, 2023 · 7 comments · Fixed by #1099
Closed

Turbo 8 refresh debounce in frontend #1093

edwinv opened this issue Dec 1, 2023 · 7 comments · Fixed by #1099

Comments

@edwinv
Copy link
Contributor

edwinv commented Dec 1, 2023

We are testing with the Turbo 8 beta in our application. Many pages in our application contain information about multiple models in our application. Because the models are related and updating eachother, we often get multiple page refreshes shortly after each other:

CleanShot 2023-12-01 at 11 41 50@2x

Both refreshes will fire a page refresh right away. Turbo already handles multiple concurrent visits and will cancel the running visit request. Even though the first refresh request is cancelled in the browser, the server will still handle the request. In our case, some pages need quite some resources to render everything. Rendering the page twice in a short period of time, knowing one render will never be used by the browser, is a waste of resources.

Maybe Turbo should also include debouncing in the frontend to prevent subsequent refreshes? A short delay in the refresh would already catch many subsequent refreshes. @jorgemanrubia do you think this is worth a PR?

@afcapel
Copy link
Collaborator

afcapel commented Dec 1, 2023

@edwinv we already added some debouncing to refresh broadcasts. It's not documented yet, I'm afraid, we still have to add the documentation before the final release.

For the debouncing to kick in you just need to ensure that all the related models are broadcasting refreshes to the same stream.

@edwinv
Copy link
Contributor Author

edwinv commented Dec 1, 2023

@afcapel Thanks! I already found the debouncing in the turbo-rails gem. One flaw in the current debouncing implementation is the reliance on a request_id, which isn't present in background jobs. I needed to add this to my test code: Turbo.with_request_id(SecureRandom.alphanumeric) { ... }. We use Sidekiq unique jobs to prevent duplicate jobs, but I understand why the current setup is better for vanilla Rails apps.

The main problem in this case are the multiple streams. In our case we have a parent/child relation. On the show of the parent, all children are also displayed. We want to update the parent and children information when it changes. So we subscribe to both the parent and all children. In Rails we have the broadcasts_refreshes on both the parent and the child, because we want to refresh when either changes. And because the information in the parent changes when the child is updated, it broadcasts twice to different streams. This prevents the server-side debouncing to kick in. Would you suggest another approach with streams in this case?

Because the children are represented in different views, we render it using a partial and within the partial we subscribe to the childs stream. This causes us to have multiple streams. I could remove the turbo_stream_from tag from the partial, but then we need to think about subscribing to the stream on every page we include the partial. Therefore I think it is better to also have debouncing in the client. I've tested with a delay of 50ms, which is barely noticeable and still prevents many duplicate requests.

@afcapel
Copy link
Collaborator

afcapel commented Dec 1, 2023

@edwinv I see. I think the best approach would be to not subscribe to the children streams from the parent page. If the child has a belongs_to :parent, touch: true relation, then the parent will be updated when the child is updated. This way you can keep the debouncing on the server side and you don't need to worry about overloaded streams on the parent page.

@edwinv
Copy link
Contributor Author

edwinv commented Dec 1, 2023

@afcapel Thanks, that would indeed fix this issue and is a feasible way forward for our project.

I'm still in favor of client side debouncing. It is not a lot of code and for performance there are hardly any downsides. The downside of doing many refreshes is large: you can easily cause a small burst of requests to a server without knowing this. In my experience the interaction between ActiveRecord touches, jobs and ActionCable is magic for many engineers. They can easily create a combination of refreshes and streams that can cause many refreshes to happen shortly after each other. Debouncing would be a valuable safeguard to prevent this.

@jorgemanrubia
Copy link
Member

I think debouncing page refreshes in the client is something that makes sense and that we'll eventually add. But even if we had that in place, I think what @afcapel suggests is a better approach here.

@brunoprietog
Copy link
Collaborator

I agree with this as well. There are cases that are not so simple, for example, a has and belongs to many asociation. If you want to broadcast a refresh signal, you should as much as possible use a Job and go through each record it belongs to and invoke the broadcast.

brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 4, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
@brunoprietog
Copy link
Collaborator

brunoprietog commented Dec 4, 2023

I've opened #1099 to explore this. Any feedback is welcome please

brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 4, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 4, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 4, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 9, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Dec 29, 2023
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Jan 7, 2024
Fix Turbo 8 refresh debounce in frontend hotwired#1093
brunoprietog added a commit to brunoprietog/turbo that referenced this issue Jan 7, 2024
Fix Turbo 8 refresh debounce in frontend hotwired#1093
domchristie pushed a commit to domchristie/turbo that referenced this issue Jul 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

4 participants