aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorGuilherme Mansur <guilherme.mansur@shopify.com>2019-05-21 17:07:27 -0400
committerGuilherme Mansur <guilherme.mansur@shopify.com>2019-05-22 14:11:03 -0400
commit218f0777d6abf1b2f933e44bd08f75f3d28c75ca (patch)
tree273f446a349d25bd7a9d899d5a90d5488e3e7a8d /activesupport
parent3453c5d4c0b54fc2a117a09ff4d5964110f5fbe8 (diff)
downloadrails-218f0777d6abf1b2f933e44bd08f75f3d28c75ca.tar.gz
rails-218f0777d6abf1b2f933e44bd08f75f3d28c75ca.tar.bz2
rails-218f0777d6abf1b2f933e44bd08f75f3d28c75ca.zip
Merge payload for EventObject subscribers
When instrumenting a block of code like: ```ruby ActiveSupport::Notifications.instrument("process_action.action_controller", raw_paylaod) do |payload| payload[:view_runtime] = render_view end ``` If we use an evented subscriber like so: ``` ruby ActiveSupport::Notifications.subscribe("process_action.action_controller", raw_payload) do |event| assert event.payload[:view_runtime] end ``` The code breaks because the underlying EventObject's payload does not have the `:view_runtime` key added during instrumentation. This is because the `EventedObject` subscriber calls the `finish` method with the `payload` of the event at the time it was pushed into the stack, before the block executes, but we want to call `finish` with the `payload` after the instrument block executes this way if the `payload` was modified during the block we have access to it. This is consistent with the other types of subscribers who don't have this bug.
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb1
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb3
-rw-r--r--activesupport/test/notifications_test.rb21
3 files changed, 24 insertions, 1 deletions
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index c37bec4ee5..97fe5bb09b 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -218,6 +218,7 @@ module ActiveSupport
def finish(name, id, payload)
stack = Thread.current[:_event_stack]
event = stack.pop
+ event.payload = payload
event.finish!
@delegate.call event
end
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index 12546511a8..6ce5aa1af4 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -53,7 +53,8 @@ module ActiveSupport
end
class Event
- attr_reader :name, :time, :end, :transaction_id, :payload, :children
+ attr_reader :name, :time, :end, :transaction_id, :children
+ attr_accessor :payload
def self.clock_gettime_supported? # :nodoc:
defined?(Process::CLOCK_PROCESS_CPUTIME_ID) &&
diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb
index 3b98749f1b..0d89189803 100644
--- a/activesupport/test/notifications_test.rb
+++ b/activesupport/test/notifications_test.rb
@@ -42,6 +42,27 @@ module Notifications
assert_operator event.duration, :>, 0
end
+ def test_subscribe_to_events_where_payload_is_changed_during_instrumentation
+ @notifier.subscribe do |event|
+ assert_equal "success!", event.payload[:my_key]
+ end
+
+ ActiveSupport::Notifications.instrument("foo") do |payload|
+ payload[:my_key] = "success!"
+ end
+ end
+
+ def test_subscribe_to_events_can_handle_nested_hashes_in_the_paylaod
+ @notifier.subscribe do |event|
+ assert_equal "success!", event.payload[:some_key][:key_one]
+ assert_equal "great_success!", event.payload[:some_key][:key_two]
+ end
+
+ ActiveSupport::Notifications.instrument("foo", some_key: { key_one: "success!" }) do |payload|
+ payload[:some_key][:key_two] = "great_success!"
+ end
+ end
+
def test_subscribe_via_top_level_api
old_notifier = ActiveSupport::Notifications.notifier
ActiveSupport::Notifications.notifier = ActiveSupport::Notifications::Fanout.new