-
Notifications
You must be signed in to change notification settings - Fork 329
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
Support for page refreshes and broadcasting #499
Conversation
Should the debouncer implementation using Also, is the debounce for multiple calls useful only for page refreshes or for the other broadcasting methods too? |
I would introduce the suppression system in a separate PR. |
This PR is the Rails companion for the Turbo changes to add page refreshes. ```ruby turbo_refreshes_with scroll method: :morph, scroll: :preserve ``` This adds new Active Record helpers to broadcast page refreshes from models: ```ruby class Board broadcast_refreshes end ``` This works great in hierarchical structures, where child record touch parent records automatically to invalidate cache: ```ruby class Column belongs_to :board, touch: true # +Board+ will trigger a page refresh on column changes end ``` You can also specify the streamable declaratively: ```ruby class Column belongs_to :board broadcast_refreshes_to :board end ``` There are also instance-level companion methods to broadcast page refreshes: - `broadcast_refresh_later` - `broadcast_refresh_later_to(*streamables)` This PR introduces a new mechanism to suppress broadcasting of turbo treams for arbitrary blocks of code: ```ruby Recording.suppressing_turbo_broadcasts do ... end ``` When broadcasting page refreshes, the system will automatically debounce multiple calls in a row to only broadcast the last one. This is meant for scenarios where you process records in mass. Because of the nature of such signals, it makes no sense to broadcast them repeatedly and individually.
4cb02fc
to
a9e011d
Compare
1b5c5b4
to
ddeeeb8
Compare
end | ||
|
||
def suppressed_turbo_broadcasts? | ||
suppressed_turbo_broadcasts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suppressed_turbo_broadcasts | |
!!suppressed_turbo_broadcasts |
A page refresh stream signals the need to reload the page. It's a global action that makes sense to aggregate when multiple signals are generated in a short period of time for a given streamable. This implementation is based on creating a thread-level debouncer associated to the set of streamables. The debouncer is implemented using concurrent-ruby's scheduled tasks.
def broadcasts_refreshes | ||
after_commit -> { broadcast_refresh_later } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this will only send broadcast refreshes to the current model's channel, right? Shouldn't it be closer to the broadcasts method and accept the stream argument or default to the model's plural name when creating the model (see #295)? Otherwise, it will send a broadcast to a channel that no one will ever be listening on (because the model is being created), right?
def broadcasts_refreshes | |
after_commit -> { broadcast_refresh_later } | |
def broadcasts_refreshes(stream = model_name.plural) | |
after_create_commit -> { broadcast_refresh_later_to(stream) } | |
after_update_commit -> { broadcast_refresh_later } | |
after_destroy_commit -> { broadcast_refresh } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sent a PR: #521
This can happen when the Debouncer has finished its work and we clear it from the current thread. The next call to refresh_debouncer_for creates a new Debouncer, but it doesn't have a scheduled_task yet. We only use the wait method in tests, to ensure that the debounces has finished its work. But if the scheduled_task is nil, we know that the debouncer has already finished its work.
Just out of curiosity, why go with the |
This PR is the Rails companion for hotwired/turbo#1019
Helper to configure page refresh directives
Helpers to broadcast page refresh actions
This adds new Active Record helpers to broadcast page refreshes from models:
This works great in hierarchical structures, where the child record touches parent records automatically to invalidate the cache:
You can also specify the streamable declaratively:
There are also instance-level companion methods to broadcast page refreshes:
broadcast_refresh_later
broadcast_refresh_later_to(*streamables)
System to suppress stream broadcasts
This PR introduces a new mechanism to suppress the broadcasting of turbo streams for arbitrary blocks of code:
System to debounce broadcasted page refresh jobs
When the broadcasting page refreshes, the system will automatically debounce multiple calls in a row to only broadcast the last one. This is meant for scenarios where you process records in mass. Because of the nature of such signals, it makes no sense to broadcast them repeatedly and individually.
The debounce implementation uses
concurrent-ruby
and thread variables under the hood.