Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorick Peterse <yorickpeterse@gmail.com>2016-03-24 17:53:38 +0300
committerYorick Peterse <yorickpeterse@gmail.com>2016-04-04 11:44:35 +0300
commit57bde0ce65caf2cbbb6a57f21435639cdaa06225 (patch)
tree3ed5e29ecdaa249bcde9a6fdb3ee7ab5732d644a /lib
parentfee7ad86273b17100d541b68c670a20ca954d673 (diff)
Cache Banzai projects/objects using RequestStore
This was originally suggested by @ayufan and modified to be a bit cleaner and use RequestStore instead of a regular Hash. By caching the output of the two methods involved the number of queries is reduced significantly. For example, for an issue with 200 notes (of which 100 reference a number of merge requests) this cuts down the amount of queries from around 6300 to around 3300.
Diffstat (limited to 'lib')
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb71
1 files changed, 67 insertions, 4 deletions
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index 34c38913474..41fd4be76ac 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -62,11 +62,53 @@ module Banzai
# Example: project.merge_requests.find
end
+ def find_object_cached(project, id)
+ if RequestStore.active?
+ cache = find_objects_cache[object_class][project.id]
+
+ if cache.key?(id)
+ cache[id]
+ else
+ cache[id] = find_object(project, id)
+ end
+ else
+ find_object(project, id)
+ end
+ end
+
+ def project_from_ref_cache(ref)
+ if RequestStore.active?
+ cache = project_refs_cache
+
+ if cache.key?(ref)
+ cache[ref]
+ else
+ cache[ref] = project_from_ref(ref)
+ end
+ else
+ project_from_ref(ref)
+ end
+ end
+
def url_for_object(object, project)
# Implement in child class
# Example: project_merge_request_url
end
+ def url_for_object_cached(object, project)
+ if RequestStore.active?
+ cache = url_for_object_cache[object_class][project.id]
+
+ if cache.key?(object)
+ cache[object]
+ else
+ cache[object] = url_for_object(object, project)
+ end
+ else
+ url_for_object(object, project)
+ end
+ end
+
def call
if object_class.reference_pattern
# `#123`
@@ -109,9 +151,9 @@ module Banzai
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
def object_link_filter(text, pattern, link_text: nil)
references_in(text, pattern) do |match, id, project_ref, matches|
- project = project_from_ref(project_ref)
+ project = project_from_ref_cache(project_ref)
- if project && object = find_object(project, id)
+ if project && object = find_object_cached(project, id)
title = object_link_title(object)
klass = reference_class(object_sym)
@@ -121,8 +163,11 @@ module Banzai
object_sym => object.id
)
- url = matches[:url] if matches.names.include?("url")
- url ||= url_for_object(object, project)
+ if matches.names.include?("url") && matches[:url]
+ url = matches[:url]
+ else
+ url = url_for_object_cached(object, project)
+ end
text = link_text || object_link_text(object, matches)
@@ -157,6 +202,24 @@ module Banzai
text
end
+
+ private
+
+ def project_refs_cache
+ RequestStore[:banzai_project_refs] ||= {}
+ end
+
+ def find_objects_cache
+ RequestStore[:banzai_find_objects_cache] ||= Hash.new do |hash, key|
+ hash[key] = Hash.new { |h, k| h[k] = {} }
+ end
+ end
+
+ def url_for_object_cache
+ RequestStore[:banzai_url_for_object] ||= Hash.new do |hash, key|
+ hash[key] = Hash.new { |h, k| h[k] = {} }
+ end
+ end
end
end
end