feat(streams): per-broadcast and per-stream durable opt-in#152
Conversation
Adds two complementary opt-in mechanisms on top of the global streams_default_broadcast_mode setting introduced in #151: 1. Per-broadcast override: stream.broadcast(html, durable: true/false) flips the mode for a single call. nil (the default) defers to the stream's own setting. 2. Per-stream pattern config: streams_durable_patterns accepts an Array of strings (exact match) or Regexps. Pgbus.stream(name) without an explicit durable: kwarg now resolves the mode through the patterns first, then falls back to streams_default_broadcast_mode. Pgbus.stream's durable: parameter changed default from true to nil so the resolver can run. Explicit durable: true/false still bypasses the resolver. Example: Pgbus.configure do |c| c.streams_durable_patterns = ["chat", /^orders:/] end Pgbus.stream("chat").broadcast(html) # durable Pgbus.stream("notifications").broadcast(html) # ephemeral Pgbus.stream("notifications").broadcast(html, durable: true) # one-off durable
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds configurable stream durability patterns to pgbus. Streams can now be marked durable via configuration pattern rules, with explicit ChangesStream Durability Configuration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
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: 1
🤖 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/configuration.rb`:
- Line 370: The current check only ensures streams_durable_patterns is an Array
but not that each element is a String or Regexp, causing later NoMethodError in
stream_durable? when non-matching types are present; update the validation at
the existing raise to iterate streams_durable_patterns and verify every element
is a String or Regexp (e.g., using is_a?(String) || is_a?(Regexp)), and if any
invalid elements exist raise an ArgumentError that lists the offending values or
their types so the user gets a clear configuration-time error referencing
streams_durable_patterns and preventing runtime failures in stream_durable?.
🪄 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: bb9ab0e8-2acf-4107-8199-e8f166a985c5
📒 Files selected for processing (5)
lib/pgbus.rblib/pgbus/configuration.rblib/pgbus/streams.rbspec/pgbus/streams/durable_opt_in_spec.rbspec/pgbus/streams/durable_patterns_spec.rb
- Use __send__(:with_connection) since PGMQ::Client#with_connection is private — unit tests passed because mocks respond to private methods, but integration tests hit the real PGMQ client - Set streams_default_broadcast_mode = :durable in integration_helper so integration specs using Pgbus.stream(name).broadcast() get durable queues for read_after verification
Summary
Builds on #151 (ephemeral broadcast mode) to add finer-grained opt-in controls for durable streams. Apps no longer have to choose between "all broadcasts ephemeral" or "all broadcasts durable" — they can mix per-broadcast and per-stream-pattern.
Two new opt-in mechanisms
1. Per-broadcast override
durable:onStream#broadcastdefaults tonil(defer to stream-level setting). Explicittrue/falseflips the mode for that one call.2. Per-stream pattern config
Pgbus.stream(name)without an explicitdurable:kwarg resolves the mode via:streams_durable_patterns(string equality or regex match)streams_default_broadcast_modefallbackExplicit
Pgbus.stream(name, durable: true/false)still bypasses the resolver.Behavior change
Pgbus.stream'sdurable:parameter default changed fromtrue→nil(resolver-driven). Apps relying on the old "always durable when called with no kwarg" behavior should either:durable: trueexplicitly, orc.streams_default_broadcast_mode = :durable, orc.streams_durable_patternsThis aligns the explicit-API path with the Turbo-patch path that #151 introduced.
Follow-up
Per-Turbo-helper overrides (
broadcasts_to :account, durable: true) tracked separately — needs to patch every Turbo broadcast helper signature, larger surface than this change. Will open a follow-up issue.Test plan
bundle exec rspec— passes (1925+ examples, 0 failures, same pre-existing I18n pendings as main)bundle exec rubocop— cleandurable: trueon ephemeral stream creates queue + sends messagedurable: falseon durable stream uses NOTIFY-only pathstreams_durable_patternsexact-string match marks stream durablestreams_durable_patternsregex match marks stream durabledurable:kwarg onPgbus.streamoverrides the resolverstreams_durable_patternsSummary by CodeRabbit
New Features
Behavior
Tests