Skip to content
Snippets Groups Projects
Commit 93fcddd7 authored by Douwe Maan's avatar Douwe Maan
Browse files

Allow ReferenceExtractor to efficiently load references from multiple texts at once

parent 251e1366
No related branches found
No related tags found
1 merge request!1090Separate rendering of Markdown reference links from redacting those the user doesn't have access to and extracting referenced objects
Pipeline #
Loading
@@ -12,7 +12,14 @@ module Gitlab
Loading
@@ -12,7 +12,14 @@ module Gitlab
# :project (required) - Current project, ignored if reference is cross-project. # :project (required) - Current project, ignored if reference is cross-project.
# :only_path - Generate path-only links. # :only_path - Generate path-only links.
class ReferenceFilter < HTML::Pipeline::Filter class ReferenceFilter < HTML::Pipeline::Filter
LazyReference = Struct.new(:klass, :ids) LazyReference = Struct.new(:klass, :ids) do
def self.load(refs)
refs.group_by(&:klass).flat_map do |klass, refs|
ids = refs.flat_map(&:ids)
klass.where(id: ids)
end
end
end
   
def self.user_can_reference?(user, node, context) def self.user_can_reference?(user, node, context)
if node.has_attribute?('data-project') if node.has_attribute?('data-project')
Loading
Loading
Loading
@@ -21,7 +21,7 @@ module Gitlab
Loading
@@ -21,7 +21,7 @@ module Gitlab
gather_references(node) gather_references(node)
end end
   
load_lazy_references load_lazy_references unless context[:load_lazy_references] == false
   
doc doc
end end
Loading
@@ -56,11 +56,8 @@ module Gitlab
Loading
@@ -56,11 +56,8 @@ module Gitlab
# Will load all references of one type using one query. # Will load all references of one type using one query.
def load_lazy_references def load_lazy_references
result[:lazy_references].each do |type, refs| result[:lazy_references].each do |type, refs|
refs.group_by(&:klass).each do |klass, refs| values = ReferenceFilter::LazyReference.load(refs)
ids = refs.map(&:ids).flatten result[:references][type].concat(values)
values = klass.find(ids)
result[:references][type].push(*values)
end
end end
end end
   
Loading
Loading
Loading
@@ -10,9 +10,10 @@ module Gitlab
Loading
@@ -10,9 +10,10 @@ module Gitlab
@current_user = current_user @current_user = current_user
end end
   
def analyze(text) def analyze(texts)
references.clear references.clear
@text = Gitlab::Markdown.render_without_gfm(text) texts = Array(texts)
@texts = texts.map { |text| Gitlab::Markdown.render_without_gfm(text) }
end end
   
%i(user label issue merge_request snippet commit commit_range).each do |type| %i(user label issue merge_request snippet commit commit_range).each do |type|
Loading
@@ -47,13 +48,25 @@ module Gitlab
Loading
@@ -47,13 +48,25 @@ module Gitlab
current_user: current_user, current_user: current_user,
# We don't actually care about the links generated # We don't actually care about the links generated
only_path: true, only_path: true,
ignore_blockquotes: true ignore_blockquotes: true,
load_lazy_references: false
} }
   
pipeline = HTML::Pipeline.new([filter, Gitlab::Markdown::ReferenceGathererFilter], context) pipeline = HTML::Pipeline.new([filter, Gitlab::Markdown::ReferenceGathererFilter], context)
result = pipeline.call(@text)
   
result[:references][filter_type] values = []
lazy_references = []
@texts.each do |text|
result = pipeline.call(text)
values.concat(result[:references][filter_type])
lazy_references.concat(result[:lazy_references][filter_type])
end
lazy_values = Gitlab::Markdown::ReferenceFilter::LazyReference.load(lazy_references)
values.concat(lazy_values)
values
end end
end end
end end
Loading
@@ -13,7 +13,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -13,7 +13,7 @@ describe Gitlab::ReferenceExtractor do
project.team << [@u_bar, :guest] project.team << [@u_bar, :guest]
   
subject.analyze('@foo, @baduser, @bar, and @offteam') subject.analyze('@foo, @baduser, @bar, and @offteam')
expect(subject.users).to eq([@u_foo, @u_bar, @u_offteam]) expect(subject.users).to match_array([@u_foo, @u_bar, @u_offteam])
end end
   
it 'ignores user mentions inside specific elements' do it 'ignores user mentions inside specific elements' do
Loading
@@ -37,7 +37,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -37,7 +37,7 @@ describe Gitlab::ReferenceExtractor do
   
> @offteam > @offteam
}) })
expect(subject.users).to eq([]) expect(subject.users).to match_array([])
end end
   
it 'accesses valid issue objects' do it 'accesses valid issue objects' do
Loading
@@ -45,7 +45,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -45,7 +45,7 @@ describe Gitlab::ReferenceExtractor do
@i1 = create(:issue, project: project) @i1 = create(:issue, project: project)
   
subject.analyze("#{@i0.to_reference}, #{@i1.to_reference}, and #{Issue.reference_prefix}999.") subject.analyze("#{@i0.to_reference}, #{@i1.to_reference}, and #{Issue.reference_prefix}999.")
expect(subject.issues).to eq([@i0, @i1]) expect(subject.issues).to match_array([@i0, @i1])
end end
   
it 'accesses valid merge requests' do it 'accesses valid merge requests' do
Loading
@@ -53,7 +53,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -53,7 +53,7 @@ describe Gitlab::ReferenceExtractor do
@m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'feature_conflict') @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'feature_conflict')
   
subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.") subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.")
expect(subject.merge_requests).to eq([@m1, @m0]) expect(subject.merge_requests).to match_array([@m1, @m0])
end end
   
it 'accesses valid labels' do it 'accesses valid labels' do
Loading
@@ -62,7 +62,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -62,7 +62,7 @@ describe Gitlab::ReferenceExtractor do
@l2 = create(:label) @l2 = create(:label)
   
subject.analyze("~#{@l0.id}, ~999, ~#{@l2.id}, ~#{@l1.id}") subject.analyze("~#{@l0.id}, ~999, ~#{@l2.id}, ~#{@l1.id}")
expect(subject.labels).to eq([@l0, @l1]) expect(subject.labels).to match_array([@l0, @l1])
end end
   
it 'accesses valid snippets' do it 'accesses valid snippets' do
Loading
@@ -71,7 +71,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -71,7 +71,7 @@ describe Gitlab::ReferenceExtractor do
@s2 = create(:project_snippet) @s2 = create(:project_snippet)
   
subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}") subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}")
expect(subject.snippets).to eq([@s0, @s1]) expect(subject.snippets).to match_array([@s0, @s1])
end end
   
it 'accesses valid commits' do it 'accesses valid commits' do
Loading
@@ -109,7 +109,7 @@ describe Gitlab::ReferenceExtractor do
Loading
@@ -109,7 +109,7 @@ describe Gitlab::ReferenceExtractor do
subject.analyze("this refers issue #{issue.to_reference(project)}") subject.analyze("this refers issue #{issue.to_reference(project)}")
extracted = subject.issues extracted = subject.issues
expect(extracted.size).to eq(1) expect(extracted.size).to eq(1)
expect(extracted).to eq([issue]) expect(extracted).to match_array([issue])
end end
end end
end end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment