Module: Upkeep::Rails::ControllerRuntime
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/upkeep/rails/controller_runtime.rb
Constant Summary collapse
- SUPPRESS_KEY =
:upkeep_rails_controller_runtime_suppressed
Class Method Summary collapse
- .install ⇒ Object
- .installed? ⇒ Boolean
- .measure_phase(payload, key) ⇒ Object
- .record_capture_payload(payload, capture) ⇒ Object
- .request_capture_profile? ⇒ Boolean
- .reset! ⇒ Object
- .suppress ⇒ Object
- .suppressed? ⇒ Boolean
- .upkeep_capture_request(&action) ⇒ Object
- .upkeep_capture_request_with_timing(action, payload) ⇒ Object
- .upkeep_reactive_continuation_request? ⇒ Boolean
-
.upkeep_stamp_change_request_id(changes) ⇒ Object
GET writes can otherwise self-refresh in a loop.
- .upkeep_subscription_request? ⇒ Boolean
- .upkeep_turbo_request_id ⇒ Object
Instance Method Summary collapse
-
#upkeep_reactive_request? ⇒ Boolean
Public override point for host controllers.
Class Method Details
.install ⇒ Object
34 35 36 37 38 39 40 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 34 def install return if @installed return unless defined?(::ActionController::Base) ::ActionController::Base.include(self) @installed = true end |
.installed? ⇒ Boolean
42 43 44 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 42 def installed? !!@installed end |
.measure_phase(payload, key) ⇒ Object
165 166 167 168 169 170 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 165 def measure_phase(payload, key) started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) yield ensure payload[key] = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at) * 1000.0).round(3) end |
.record_capture_payload(payload, capture) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 148 def record_capture_payload(payload, capture) payload[:response_status] = capture.response_status payload[:response_content_type] = capture.response_content_type payload[:response_media_type] = capture.response_media_type payload[:html_response] = capture.html_response? payload[:response_successful] = capture.successful? payload[:html_bytes] = capture.html.bytesize payload[:graph_frames] = capture.recorder.graph.frame_nodes.size payload[:graph_dependencies] = capture.recorder.graph.dependency_nodes.size capture.timings.each do |phase, ms| payload[:"capture_#{phase}"] = ms end capture.counters.each do |counter, value| payload[:"capture_#{counter}"] = value end end |
.request_capture_profile? ⇒ Boolean
182 183 184 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 182 def request_capture_profile? ActiveSupport::Notifications.notifier.listening?(Upkeep::Rails::REQUEST_CAPTURE) end |
.reset! ⇒ Object
46 47 48 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 46 def reset! @installed = false end |
.suppress ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 50 def suppress previous = Thread.current[SUPPRESS_KEY] Thread.current[SUPPRESS_KEY] = true yield ensure Thread.current[SUPPRESS_KEY] = previous end |
.suppressed? ⇒ Boolean
58 59 60 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 58 def suppressed? Thread.current[SUPPRESS_KEY] end |
.upkeep_capture_request(&action) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 64 def upkeep_capture_request(&action) return action.call if ControllerRuntime.suppressed? return action.call if Upkeep::Runtime::Observation.recorder payload = { controller: self.class.name, action: action_name, method: request.request_method, path: request.fullpath, subscription_request: upkeep_subscription_request? } ActiveSupport::Notifications.instrument(Upkeep::Rails::REQUEST_CAPTURE, payload) do upkeep_capture_request_with_timing(action, payload) end end |
.upkeep_capture_request_with_timing(action, payload) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 80 def upkeep_capture_request_with_timing(action, payload) measure_phase(payload, :deliver_pending_ms) { Upkeep::Rails.deliver_changes_now! } result = nil capture = nil changes = [] measure_phase(payload, :change_capture_ms) do _captured, changes = Upkeep::Runtime::ChangeLog.capture do if payload.fetch(:subscription_request) capture = Upkeep::Capture::Request.call(self, profile: request_capture_profile?) { action.call } result = capture.action_result else measure_phase(payload, :action_ms) { result = action.call } end end end changes = upkeep_stamp_change_request_id(changes) record_capture_payload(payload, capture) if capture measure_phase(payload, :deliver_changes_ms) do if capture Upkeep::Rails.deliver_changes_now!(changes) else Upkeep::Rails.deliver_changes!(changes) end end registration = nil if capture measure_phase(payload, :register_ms) do registration = Upkeep::Rails.register_controller_subscription(self, capture) end end payload[:registered] = !!registration if capture && registration measure_phase(payload, :inject_ms) do Upkeep::Rails::ClientSubscription.headers_for( identity: registration.identity, subscription: registration.subscription ).each { |name, value| response.headers[name] = value } response.body = Upkeep::Rails::ClientSubscription.inject( capture.html, identity: registration.identity, subscription: registration.subscription ) end payload[:subscription_id] = registration.subscription.id end result end |
.upkeep_reactive_continuation_request? ⇒ Boolean
176 177 178 179 180 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 176 def upkeep_reactive_continuation_request? request.headers["Turbo-Frame"].present? && request.headers[ClientSubscription::ID_HEADER].present? && request.headers[ClientSubscription::TOKEN_HEADER].present? end |
.upkeep_stamp_change_request_id(changes) ⇒ Object
GET writes can otherwise self-refresh in a loop. Mutation deliveries must still reach the originating tab when the response omits an affected region.
134 135 136 137 138 139 140 141 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 134 def upkeep_stamp_change_request_id(changes) return changes unless request.get? || request.head? request_id = upkeep_turbo_request_id return changes unless request_id changes.map { |change| change.respond_to?(:merge) ? change.merge(request_id: request_id) : change } end |
.upkeep_subscription_request? ⇒ Boolean
172 173 174 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 172 def upkeep_subscription_request? upkeep_reactive_request? && request.format.html? && (request.get? || request.head?) end |
.upkeep_turbo_request_id ⇒ Object
143 144 145 146 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 143 def upkeep_turbo_request_id turbo_request_id = ::Turbo.current_request_id if defined?(::Turbo) && ::Turbo.respond_to?(:current_request_id) turbo_request_id || request.headers["X-Turbo-Request-Id"] end |
Instance Method Details
#upkeep_reactive_request? ⇒ Boolean
Public override point for host controllers. Return false to skip subscription capture and registration for this request. Writes are still captured and can update subscribed pages.
26 27 28 29 30 |
# File 'lib/upkeep/rails/controller_runtime.rb', line 26 def upkeep_reactive_request? return true if Upkeep::Rails.configuration.request_activation == :all self.class.upkeep_reactive_actions.include?(action_name) || upkeep_reactive_continuation_request? end |