Reduce Namespace queries in UserReferenceFilter
This changes UserReferenceFilter so it operates using the following steps: 1. Grab all username references from the input document. 2. Query the corresponding Namespace objects using a single query. 3. Iterate over all nodes to build links while re-using the objects queried in step 2. The impact of these changes is that a comment mentioning 5 different usernames no longer runs 5 different queries (1 for every username), instead it only runs a single query.
This commit is contained in:
parent
8a6c3f27e9
commit
01575e9966
|
@ -26,6 +26,7 @@ v 8.9.0 (unreleased)
|
|||
- Measure queue duration between gitlab-workhorse and Rails
|
||||
- Make authentication service for Container Registry to be compatible with < Docker 1.11
|
||||
- Add Application Setting to configure Container Registry token expire delay (default 5min)
|
||||
- Reduce number of SQL queries when rendering user references
|
||||
|
||||
v 8.8.3
|
||||
- Fix incorrect links on pipeline page when merge request created from fork
|
||||
|
|
|
@ -29,7 +29,7 @@ module Banzai
|
|||
ref_pattern = User.reference_pattern
|
||||
ref_pattern_start = /\A#{ref_pattern}\z/
|
||||
|
||||
each_node do |node|
|
||||
nodes.each do |node|
|
||||
if text_node?(node)
|
||||
replace_text_when_pattern_matches(node, ref_pattern) do |content|
|
||||
user_link_filter(content)
|
||||
|
@ -59,7 +59,7 @@ module Banzai
|
|||
self.class.references_in(text) do |match, username|
|
||||
if username == 'all'
|
||||
link_to_all(link_text: link_text)
|
||||
elsif namespace = Namespace.find_by(path: username)
|
||||
elsif namespace = namespaces[username]
|
||||
link_to_namespace(namespace, link_text: link_text) || match
|
||||
else
|
||||
match
|
||||
|
@ -67,6 +67,31 @@ module Banzai
|
|||
end
|
||||
end
|
||||
|
||||
# Returns a Hash containing all Namespace objects for the username
|
||||
# references in the current document.
|
||||
#
|
||||
# The keys of this Hash are the namespace paths, the values the
|
||||
# corresponding Namespace objects.
|
||||
def namespaces
|
||||
@namespaces ||=
|
||||
Namespace.where(path: usernames).each_with_object({}) do |row, hash|
|
||||
hash[row.path] = row
|
||||
end
|
||||
end
|
||||
|
||||
# Returns all usernames referenced in the current document.
|
||||
def usernames
|
||||
refs = Set.new
|
||||
|
||||
nodes.each do |node|
|
||||
node.to_html.scan(User.reference_pattern) do
|
||||
refs << $~[:user]
|
||||
end
|
||||
end
|
||||
|
||||
refs.to_a
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def urls
|
||||
|
|
|
@ -136,4 +136,23 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
|
|||
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
describe '#namespaces' do
|
||||
it 'returns a Hash containing all Namespaces' do
|
||||
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>")
|
||||
filter = described_class.new(document, project: project)
|
||||
ns = user.namespace
|
||||
|
||||
expect(filter.namespaces).to eq({ ns.path => ns })
|
||||
end
|
||||
end
|
||||
|
||||
describe '#usernames' do
|
||||
it 'returns the usernames mentioned in a document' do
|
||||
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>")
|
||||
filter = described_class.new(document, project: project)
|
||||
|
||||
expect(filter.usernames).to eq([user.username])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue