feat(streams): per-Turbo-helper durable opt-in#154
Conversation
Add `durable:` kwarg support to all Turbo broadcast helpers so apps can control durable mode at the call site instead of relying solely on global config (`streams_durable_patterns` / `streams_default_broadcast_mode`). Approach: a thin `BroadcastableOverride` module prepended onto `Turbo::Broadcastable` extracts `durable:` from kwargs and sets a thread-local that `TurboBroadcastable#broadcast_stream_to` reads. The thread-local is always cleaned up after the broadcast, even on error. Supported APIs: - `broadcasts_to :account, durable: true` (class-level declarative) - `broadcasts_refreshes_to :board, durable: true` - `broadcast_replace_to(record, durable: true)` (instance-level direct) - All other broadcast helpers (append, prepend, update, remove, action, refresh, and their _later_to variants) When `durable:` is omitted, resolution falls back to the existing chain: streams_durable_patterns → streams_default_broadcast_mode. Closes #153
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a BroadcastableOverride that accepts ChangesDurable broadcast propagation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/pgbus/streams/broadcastable_override.rb`:
- Around line 18-35: BROADCAST_METHODS is missing Turbo instance methods so
calls like broadcast_after_to, broadcast_before_to, broadcast_render_to, and
broadcast_render_later_to bypass the override and can't accept the durable:
kwarg; update the BROADCAST_METHODS constant to include these four symbols
(broadcast_after_to, broadcast_before_to, broadcast_render_to,
broadcast_render_later_to) alongside the existing entries so the override logic
in this file applies to them as well.
- Around line 104-109: The install! method in Turbo::Broadcastable uses
mod.singleton_class.prepend(ClassMethods) for Module cases, which doesn't
replace the ClassMethods that get applied when other modules/classes include
this module; change that call to mod.extend(ClassMethods) so the patched
ClassMethods are applied to any module or class that includes or extends
Turbo::Broadcastable (update the install! method that references mod,
ClassMethods, and singleton_class.prepend to use mod.extend(ClassMethods)
instead).
In `@lib/pgbus/streams/turbo_broadcastable.rb`:
- Around line 39-45: The thread-local override
Thread.current[:pgbus_broadcast_durable] is lost when turbo enqueues a
background job, so persist the caller's durable intent into the job payload and
read it when the job executes: change places that currently read
Thread.current[:pgbus_broadcast_durable] (e.g., in broadcast_action_to /
broadcast_stream_to and the Pgbus wrapper around Pgbus.stream(name, durable:
durable).broadcast) to capture the resolved durable boolean and pass it as an
explicit argument into the enqueued Turbo::Streams::ActionBroadcastJob (or
include it in the serialized broadcast payload), and update the job runner to
extract that durable flag and call Pgbus.stream(..., durable: durable).broadcast
using that explicit flag instead of re-reading Thread.current.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 25196b85-aee9-4972-b4b4-b930c2c5ae86
📒 Files selected for processing (6)
lib/pgbus/engine.rblib/pgbus/streams/broadcastable_override.rblib/pgbus/streams/turbo_broadcastable.rbspec/pgbus/streams/broadcastable_class_methods_spec.rbspec/pgbus/streams/broadcastable_override_spec.rbspec/pgbus/streams/turbo_broadcastable_spec.rb
- Add missing broadcast methods (broadcast_after_to, broadcast_before_to, broadcast_render_to, broadcast_render_later_to) to BROADCAST_METHODS - Remove _later_to async variants from override list since thread-local cannot survive into background job execution context - Use synchronous broadcast calls in broadcasts_to durable: callbacks (pgbus handles transactional deferral natively via after_commit) - Fix ClassMethods installation: prepend onto Turbo::Broadcastable::ClassMethods instead of singleton_class.prepend, so ActiveSupport::Concern includers pick up the overridden broadcasts_to/broadcasts_refreshes_to
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/pgbus/streams/broadcastable_override.rb`:
- Around line 23-34: BROADCAST_METHODS currently includes
broadcast_render_later_to which contradicts the file docs and causes
with_pgbus_durable wrapping to be applied only at enqueue time; remove
broadcast_render_later_to from the BROADCAST_METHODS array so it is not wrapped
by with_pgbus_durable (leave all other methods intact), and ensure any
references to with_pgbus_durable or tests that stub broadcast_render_later_to
are updated to treat the _later_to variant as a background-job enqueue (i.e., do
not expect durable wrapping to be effective at perform time); this targets the
BROADCAST_METHODS constant and the with_pgbus_durable wrapper logic around those
methods and prevents incorrect thread-local assumptions when
Turbo::Streams::BroadcastJob#perform runs.
In `@spec/pgbus/streams/broadcastable_class_methods_spec.rb`:
- Around line 168-175: The specs are not exercising the real
Turbo::Broadcastable::ClassMethods install path because they extend the test
class with described_class directly; instead, stub a nested
Turbo::Broadcastable::ClassMethods module on Turbo::Broadcastable, call
Pgbus::Streams::BroadcastableOverride.install!(Turbo::Broadcastable) to let it
prepend into Turbo::Broadcastable::ClassMethods, and then include
Turbo::Broadcastable into the test class (rather than
klass.extend(described_class)); apply the same change to the other occurrence
around lines 272-278 so the spec fails if install! stops prepending onto
Turbo::Broadcastable::ClassMethods.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: fa19d65d-e674-4341-9c05-daeb789cdba5
📒 Files selected for processing (3)
lib/pgbus/streams/broadcastable_override.rbspec/pgbus/streams/broadcastable_class_methods_spec.rbspec/pgbus/streams/broadcastable_override_spec.rb
It's a _later_to variant that enqueues BroadcastJob — the thread-local cannot survive into the job execution context.
Summary
durable:kwarg to all Turbo broadcast helpers (broadcast_replace_to,broadcast_append_to, etc.) and their_later_tovariantsdurable:option to class-level declarations (broadcasts_to :account, durable: true,broadcasts_refreshes_to :board, durable: true)Thread.current[:pgbus_broadcast_durable]) to pass the override through the existingbroadcast_stream_tofunnel — minimal patching surface, no turbo-rails internal signatures modifiedstreams_durable_patterns→streams_default_broadcast_mode) whendurable:is omitted — fully backwards compatibleNew files
lib/pgbus/streams/broadcastable_override.rb— prepended ontoTurbo::Broadcastablespec/pgbus/streams/broadcastable_override_spec.rb— 16 examples covering instance-leveldurable:forwardingspec/pgbus/streams/broadcastable_class_methods_spec.rb— 6 examples coveringbroadcasts_to/broadcasts_refreshes_toclass methodsModified files
lib/pgbus/streams/turbo_broadcastable.rb— reads thread-local before falling back to configlib/pgbus/engine.rb— installsBroadcastableOverridepatch at bootspec/pgbus/streams/turbo_broadcastable_spec.rb— 3 new examples for thread-local integrationCloses #153
Test plan
broadcast_replace_to(record, durable: true)forwardsdurable: truetoPgbus.streambroadcast_replace_to(record, durable: false)forwardsdurable: falsedurable:falls back tostreams_default_broadcast_modeconfigdurable:correctlybroadcast_action_toandbroadcast_action_later_toforwarddurable:broadcasts_to :account, durable: truesets durable on create/update/destroy callbacksbroadcasts_refreshes_to :board, durable: truesets durable on commit callbackfalseoverrides durable config modeSummary by CodeRabbit
New Features
Tests