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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
commitb39512ed755239198a9c294b6a45e65c05900235 (patch)
treed234a3efade1de67c46b9e5a38ce813627726aa7 /lib/gitlab/utils
parentd31474cf3b17ece37939d20082b07f6657cc79a9 (diff)
Add latest changes from gitlab-org/gitlab@15-3-stable-eev15.3.0-rc42
Diffstat (limited to 'lib/gitlab/utils')
-rw-r--r--lib/gitlab/utils/batch_loader.rb23
-rw-r--r--lib/gitlab/utils/link_header_parser.rb46
-rw-r--r--lib/gitlab/utils/strong_memoize.rb73
-rw-r--r--lib/gitlab/utils/usage_data.rb4
4 files changed, 144 insertions, 2 deletions
diff --git a/lib/gitlab/utils/batch_loader.rb b/lib/gitlab/utils/batch_loader.rb
new file mode 100644
index 00000000000..67ade0633e2
--- /dev/null
+++ b/lib/gitlab/utils/batch_loader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ module BatchLoader
+ # Clears batched items under the specified batch key
+ # https://github.com/exAspArk/batch-loader#batch-key
+ def self.clear_key(batch_key)
+ return if ::BatchLoader::Executor.current.nil?
+
+ items_to_clear = ::BatchLoader::Executor.current.items_by_block.select do |k, v|
+ # The Hash key here is [source_location, batch_key], so we just check k[1]
+ k[1] == batch_key
+ end
+
+ items_to_clear.each do |k, v|
+ ::BatchLoader::Executor.current.items_by_block.delete(k)
+ ::BatchLoader::Executor.current.loaded_values_by_block.delete(k)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/link_header_parser.rb b/lib/gitlab/utils/link_header_parser.rb
new file mode 100644
index 00000000000..d98c237baf3
--- /dev/null
+++ b/lib/gitlab/utils/link_header_parser.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ # Parses Link http headers (as defined in https://www.rfc-editor.org/rfc/rfc5988.txt)
+ #
+ # The URI-references with their relation type are extracted and returned as a hash
+ # Example:
+ #
+ # header = '<http://test.org/TheBook/chapter2>; rel="previous", <http://test.org/TheBook/chapter4>; rel="next"'
+ #
+ # Gitlab::Utils::LinkHeaderParser.new(header).parse
+ # {
+ # previous: {
+ # uri: #<URI::HTTP http://test.org/TheBook/chapter2>
+ # },
+ # next: {
+ # uri: #<URI::HTTP http://test.org/TheBook/chapter4>
+ # }
+ # }
+ class LinkHeaderParser
+ REL_PATTERN = %r{rel="(\w+)"}.freeze
+ # to avoid parse really long URIs we limit the amount of characters allowed
+ URI_PATTERN = %r{<(.{1,500})>}.freeze
+
+ def initialize(header)
+ @header = header
+ end
+
+ def parse
+ return {} if @header.blank?
+
+ links = @header.split(',')
+ result = {}
+ links.each do |link|
+ direction = link[REL_PATTERN, 1]&.to_sym
+ uri = link[URI_PATTERN, 1]
+
+ result[direction] = { uri: URI(uri) } if direction && uri
+ end
+
+ result
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index 3c954f817a7..50b8428113d 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -21,6 +21,20 @@ module Gitlab
# end
# end
#
+ # Or like:
+ #
+ # include Gitlab::Utils::StrongMemoize
+ #
+ # def trigger_from_token
+ # Ci::Trigger.find_by_token(params[:token].to_s)
+ # end
+ # strong_memoize_attr :trigger_from_token
+ #
+ # strong_memoize_attr :enabled?, :enabled
+ # def enabled?
+ # Feature.enabled?(:some_feature)
+ # end
+ #
def strong_memoize(name)
key = ivar(name)
@@ -40,6 +54,34 @@ module Gitlab
remove_instance_variable(key) if instance_variable_defined?(key)
end
+ module StrongMemoizeClassMethods
+ def strong_memoize_attr(method_name, member_name = nil)
+ member_name ||= method_name
+
+ if method_defined?(method_name) || private_method_defined?(method_name)
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :do_strong_memoize, self, method_name, member_name)
+ else
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :queue_strong_memoize, self, method_name, member_name)
+ end
+ end
+
+ def method_added(method_name)
+ super
+
+ if member_name = StrongMemoize
+ .send(:strong_memoize_queue, self).delete(method_name) # rubocop:disable GitlabSecurity/PublicSend
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :do_strong_memoize, self, method_name, member_name)
+ end
+ end
+ end
+
+ def self.included(base)
+ base.singleton_class.prepend(StrongMemoizeClassMethods)
+ end
+
private
# Convert `"name"`/`:name` into `:@name`
@@ -54,6 +96,37 @@ module Gitlab
raise ArgumentError, "Invalid type of '#{name}'"
end
end
+
+ class <<self
+ private
+
+ def strong_memoize_queue(klass)
+ klass.instance_variable_get(:@strong_memoize_queue) || klass.instance_variable_set(:@strong_memoize_queue, {})
+ end
+
+ def queue_strong_memoize(klass, method_name, member_name)
+ strong_memoize_queue(klass)[method_name] = member_name
+ end
+
+ def do_strong_memoize(klass, method_name, member_name)
+ method = klass.instance_method(method_name)
+
+ # Methods defined within a class method are already public by default, so we don't need to
+ # explicitly make them public.
+ scope = %i[private protected].find do |scope|
+ klass.send("#{scope}_instance_methods") # rubocop:disable GitlabSecurity/PublicSend
+ .include? method_name
+ end
+
+ klass.define_method(method_name) do |*args, &block|
+ strong_memoize(member_name) do
+ method.bind_call(self, *args, &block)
+ end
+ end
+
+ klass.send(scope, method_name) if scope # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
end
end
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 4d1b234ae54..19bdeefed7e 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -196,7 +196,7 @@ module Gitlab
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
with_duration do
- if block_given?
+ if block
yield
else
value
@@ -209,7 +209,7 @@ module Gitlab
def redis_usage_data(counter = nil, &block)
with_duration do
- if block_given?
+ if block
redis_usage_counter(&block)
elsif counter.present?
redis_usage_data_totals(counter)