Module: ReactOnRailsPro::Stream

Extended by:
ActiveSupport::Concern
Defined in:
lib/react_on_rails_pro/concerns/stream.rb

Overview

rubocop:disable Metrics/ModuleLength

Defined Under Namespace

Classes: RendererServerTimingAttemptCollector

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.record_renderer_response_headers(headers) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 80

def record_renderer_response_headers(headers)
  collector = renderer_server_timing_collector
  return unless collector

  server_timing_values(headers).each do |value|
    entry = sanitize_server_timing_header_entry(value)
    next if entry.blank?

    collector << entry
    renderer_server_timing_attempt_collector&.append(entry, collector:)
  end
end

.renderer_server_timing_collectorObject



93
94
95
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 93

def renderer_server_timing_collector
  Thread.current[RENDERER_SERVER_TIMING_COLLECTOR_KEY]
end

.renderer_server_timing_collector=(collector) ⇒ Object



97
98
99
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 97

def renderer_server_timing_collector=(collector)
  Thread.current[RENDERER_SERVER_TIMING_COLLECTOR_KEY] = collector
end

.renderer_server_timing_collector_snapshotObject



109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 109

def renderer_server_timing_collector_snapshot
  collector = renderer_server_timing_collector
  return unless collector

  attempt_collector = RendererServerTimingAttemptCollector.new(
    collector:,
    previous_attempt_collector: renderer_server_timing_attempt_collector
  )
  self.renderer_server_timing_attempt_collector = attempt_collector

  attempt_collector
end

.restore_renderer_server_timing_collector_snapshot(attempt_collector) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 122

def restore_renderer_server_timing_collector_snapshot(attempt_collector)
  return unless attempt_collector

  collector = renderer_server_timing_collector
  return unless collector.equal?(attempt_collector.collector)

  attempt_collector.remove_appended_entries
ensure
  if attempt_collector && renderer_server_timing_attempt_collector.equal?(attempt_collector)
    self.renderer_server_timing_attempt_collector = attempt_collector.previous_attempt_collector
  end
end

.with_renderer_server_timing_collector(collector) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 101

def with_renderer_server_timing_collector(collector)
  previous_collector = renderer_server_timing_collector
  self.renderer_server_timing_collector = collector
  yield
ensure
  self.renderer_server_timing_collector = previous_collector
end

Instance Method Details

#stream_view_containing_react_components(template:, close_stream_at_end: true, content_type: nil, rsc_stream_observability: false, **render_options) ⇒ Object

Note:

The stream_react_component helper is defined in the react_on_rails gem. For more details, refer to lib/react_on_rails/helper.rb in the react_on_rails repository.

Streams React components within a specified template to the client.

components must be added to the view using the stream_react_component helper.

Examples:

stream_view_containing_react_components(template: 'path/to/your/template')
stream_view_containing_react_components(
  template: 'path/to/your/template',
  close_stream_at_end: false,
  layout: false
)

Parameters:

  • template (String)

    The path to the template file to be streamed.

  • close_stream_at_end (Boolean) (defaults to: true)

    Whether to automatically close the stream after rendering (default: true).

  • content_type (String, nil) (defaults to: nil)

    Optional response content type. Set after rendering but before the first stream write, overriding any content type inferred from the template format. When using a non-HTML formats: value (for example [:text]), pass content_type too unless committing the format-derived MIME type is intentional.

  • rsc_stream_observability (Boolean) (defaults to: false)

    Whether to emit browser-observable streamed RSC timing marks.

  • render_options (Hash)

    Additional options to pass to render_to_string.

See Also:

  • ReactOnRails::Helper#stream_react_component


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/react_on_rails_pro/concerns/stream.rb', line 220

def stream_view_containing_react_components(
  template:, close_stream_at_end: true, content_type: nil, rsc_stream_observability: false, **render_options
)
  previous_rsc_stream_observability_state = current_rsc_stream_observability_state
  require_streaming_dependencies
  warn_on_non_html_formats_without_content_type(render_options[:formats], content_type)
  initialize_rsc_stream_observability_state(rsc_stream_observability)
  parent_context = ReactOnRailsPro::OpenTelemetry.capture_context

  Sync do |parent_task|
    ReactOnRailsPro::OpenTelemetry.with_context(parent_context) do
      ReactOnRailsPro::Stream.with_renderer_server_timing_collector(renderer_server_timing_collector_for_stream) do
        stream_view_containing_react_components_in_sync(
          parent_task,
          template:,
          close_stream_at_end:,
          content_type:,
          render_options:
        )
      end
    end
  end
ensure
  @react_on_rails_pending_stream_cache_writes = nil
  restore_rsc_stream_observability_state(previous_rsc_stream_observability_state)
end