diff options
author | Carlhuda <carlhuda@engineyard.com> | 2010-03-01 17:33:59 -0800 |
---|---|---|
committer | Carlhuda <carlhuda@engineyard.com> | 2010-03-01 17:45:37 -0800 |
commit | fc0882ba5a0f18281736859718252042b15614ad (patch) | |
tree | 959bd861403369fc2d615104a102663a9b9a8da2 | |
parent | c88360ef3651702ca8f7f600e15774f51c84698b (diff) | |
download | rails-fc0882ba5a0f18281736859718252042b15614ad.tar.gz rails-fc0882ba5a0f18281736859718252042b15614ad.tar.bz2 rails-fc0882ba5a0f18281736859718252042b15614ad.zip |
Optimize AS::Notifications to remember which subscribers don't match and not run them. This will allow notifications that are only useful in dev or testing to run efficiently in production.
-rw-r--r-- | activesupport/lib/active_support/notifications.rb | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/notifications/fanout.rb | 15 | ||||
-rw-r--r-- | activesupport/test/notifications_test.rb | 31 |
3 files changed, 42 insertions, 6 deletions
diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index fca2efd969..3f1fe64e9b 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -44,7 +44,7 @@ module ActiveSupport class << self attr_writer :notifier - delegate :publish, :subscribe, :to => :notifier + delegate :publish, :subscribe, :unsubscribe, :to => :notifier delegate :instrument, :to => :instrumenter def notifier diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index e08011e23f..cd60054862 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -5,6 +5,7 @@ module ActiveSupport class Fanout def initialize @subscribers = [] + @listeners_for = {} end def bind(pattern) @@ -12,16 +13,22 @@ module ActiveSupport end def subscribe(pattern = nil, &block) + @listeners_for.clear @subscribers << Subscriber.new(pattern, &block) @subscribers.last end def unsubscribe(subscriber) @subscribers.delete(subscriber) + @listeners_for.clear end - def publish(*args) - @subscribers.each { |s| s.publish(*args) } + def publish(name, *args) + if listeners = @listeners_for[name] + listeners.each { |s| s.publish(name, *args) } + else + @listeners_for[name] = @subscribers.select { |s| s.publish(name, *args) } + end end # This is a sync queue, so there is not waiting. @@ -53,7 +60,9 @@ module ActiveSupport end def publish(*args) - push(*args) if matches?(args.first) + return unless matches?(args.first) + push(*args) + true end def drained? diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index baee779b8a..67c3527e23 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -20,15 +20,20 @@ module Notifications end class UnsubscribeTest < TestCase - def unsubscribing_removes_a_subscription + def test_unsubscribing_removes_a_subscription @notifier.publish :foo @notifier.wait assert_equal [[:foo]], @events @notifier.unsubscribe(@subscription) - @notifier.publish :bar + @notifier.publish :foo @notifier.wait assert_equal [[:foo]], @events end + + private + def event(*args) + args + end end class SyncPubSubTest < TestCase @@ -38,6 +43,28 @@ module Notifications assert_equal [[:foo]], @events end + def test_publishing_multiple_times_works + @notifier.publish :foo + @notifier.publish :foo + @notifier.wait + assert_equal [[:foo], [:foo]], @events + end + + def test_publishing_after_a_new_subscribe_works + @notifier.publish :foo + @notifier.publish :foo + + @notifier.subscribe("not_existant") do |*args| + @events << ActiveSupport::Notifications::Event.new(*args) + end + + @notifier.publish :foo + @notifier.publish :foo + @notifier.wait + + assert_equal [[:foo]] * 4, @events + end + def test_log_subscriber_with_pattern events = [] @notifier.subscribe('1') { |*args| events << args } |