aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@github.com>2019-02-01 13:36:25 -0800
committerGitHub <noreply@github.com>2019-02-01 13:36:25 -0800
commit2ccbddb48c96b0cda9641961541d7266591a3db7 (patch)
tree9fa638fcf39ee2a69ea5d99d8678391ff57e968e
parentcaf8dbc1591c64ae4fd9253a714903710f46f7ce (diff)
parent211222cc182218c06e9a1b094f48d9e96e905865 (diff)
downloadrails-2ccbddb48c96b0cda9641961541d7266591a3db7.tar.gz
rails-2ccbddb48c96b0cda9641961541d7266591a3db7.tar.bz2
rails-2ccbddb48c96b0cda9641961541d7266591a3db7.zip
Merge pull request #35133 from jhawthorn/faster_notifications
Make Notifications::Fanout faster after changing subscriptions
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb31
1 files changed, 23 insertions, 8 deletions
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index 4e4ca70942..11721db103 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -13,7 +13,8 @@ module ActiveSupport
include Mutex_m
def initialize
- @subscribers = []
+ @string_subscribers = Hash.new { |h, k| h[k] = [] }
+ @other_subscribers = []
@listeners_for = Concurrent::Map.new
super
end
@@ -21,8 +22,13 @@ module ActiveSupport
def subscribe(pattern = nil, block = Proc.new)
subscriber = Subscribers.new pattern, block
synchronize do
- @subscribers << subscriber
- @listeners_for.clear
+ if String === pattern
+ @string_subscribers[pattern] << subscriber
+ @listeners_for.delete(pattern)
+ else
+ @other_subscribers << subscriber
+ @listeners_for.clear
+ end
end
subscriber
end
@@ -31,12 +37,18 @@ module ActiveSupport
synchronize do
case subscriber_or_name
when String
- @subscribers.reject! { |s| s.matches?(subscriber_or_name) }
+ @string_subscribers[subscriber_or_name].clear
+ @listeners_for.delete(subscriber_or_name)
else
- @subscribers.delete(subscriber_or_name)
+ pattern = subscriber_or_name.try(:pattern)
+ if String === pattern
+ @string_subscribers[pattern].delete(subscriber_or_name)
+ @listeners_for.delete(pattern)
+ else
+ @other_subscribers.delete(subscriber_or_name)
+ @listeners_for.clear
+ end
end
-
- @listeners_for.clear
end
end
@@ -56,7 +68,8 @@ module ActiveSupport
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
@listeners_for[name] || synchronize do
# use synchronisation when accessing @subscribers
- @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
+ @listeners_for[name] ||=
+ @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
end
end
@@ -101,6 +114,8 @@ module ActiveSupport
end
class Evented #:nodoc:
+ attr_reader :pattern
+
def initialize(pattern, delegate)
@pattern = pattern
@delegate = delegate