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:
Diffstat (limited to 'app/services/protected_branches')
-rw-r--r--app/services/protected_branches/base_service.rb4
-rw-r--r--app/services/protected_branches/cache_service.rb68
-rw-r--r--app/services/protected_branches/create_service.rb2
-rw-r--r--app/services/protected_branches/destroy_service.rb2
-rw-r--r--app/services/protected_branches/update_service.rb2
5 files changed, 77 insertions, 1 deletions
diff --git a/app/services/protected_branches/base_service.rb b/app/services/protected_branches/base_service.rb
index f48e02ab4b5..d26c1b148bf 100644
--- a/app/services/protected_branches/base_service.rb
+++ b/app/services/protected_branches/base_service.rb
@@ -13,5 +13,9 @@ module ProtectedBranches
def after_execute(*)
# overridden in EE::ProtectedBranches module
end
+
+ def refresh_cache
+ CacheService.new(@project, @current_user, @params).refresh
+ end
end
end
diff --git a/app/services/protected_branches/cache_service.rb b/app/services/protected_branches/cache_service.rb
new file mode 100644
index 00000000000..8c521f4ebcb
--- /dev/null
+++ b/app/services/protected_branches/cache_service.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module ProtectedBranches
+ class CacheService < ProtectedBranches::BaseService
+ CACHE_ROOT_KEY = 'cache:gitlab:protected_branch'
+ TTL_UNSET = -1
+ CACHE_EXPIRE_IN = 1.day
+ CACHE_LIMIT = 1000
+
+ def fetch(ref_name, dry_run: false)
+ record = OpenSSL::Digest::SHA256.hexdigest(ref_name)
+
+ Gitlab::Redis::Cache.with do |redis|
+ cached_result = redis.hget(redis_key, record)
+
+ decoded_result = Gitlab::Redis::Boolean.decode(cached_result) unless cached_result.nil?
+
+ # If we're dry-running, don't break because we need to check against
+ # the real value to ensure the cache is working properly.
+ # If the result is nil we'll need to run the block, so don't break yet.
+ break decoded_result unless dry_run || decoded_result.nil?
+
+ calculated_value = yield
+
+ check_and_log_discrepancy(decoded_result, calculated_value, ref_name) if dry_run
+
+ redis.hset(redis_key, record, Gitlab::Redis::Boolean.encode(calculated_value))
+
+ # We don't want to extend cache expiration time
+ if redis.ttl(redis_key) == TTL_UNSET
+ redis.expire(redis_key, CACHE_EXPIRE_IN)
+ end
+
+ # If the cache record has too many elements, then something went wrong and
+ # it's better to drop the cache key.
+ if redis.hlen(redis_key) > CACHE_LIMIT
+ redis.unlink(redis_key)
+ end
+
+ calculated_value
+ end
+ end
+
+ def refresh
+ Gitlab::Redis::Cache.with { |redis| redis.unlink(redis_key) }
+ end
+
+ private
+
+ def check_and_log_discrepancy(cached_value, real_value, ref_name)
+ return if cached_value.nil?
+ return if cached_value == real_value
+
+ encoded_ref_name = Gitlab::EncodingHelper.encode_utf8_with_replacement_character(ref_name)
+
+ log_error(
+ 'class' => self.class.name,
+ 'message' => "Cache mismatch '#{encoded_ref_name}': cached value: #{cached_value}, real value: #{real_value}",
+ 'project_id' => @project.id,
+ 'project_path' => @project.full_path
+ )
+ end
+
+ def redis_key
+ @redis_key ||= [CACHE_ROOT_KEY, @project.id].join(':')
+ end
+ end
+end
diff --git a/app/services/protected_branches/create_service.rb b/app/services/protected_branches/create_service.rb
index dada449989a..903addf7afc 100644
--- a/app/services/protected_branches/create_service.rb
+++ b/app/services/protected_branches/create_service.rb
@@ -7,6 +7,8 @@ module ProtectedBranches
save_protected_branch
+ refresh_cache
+
protected_branch
end
diff --git a/app/services/protected_branches/destroy_service.rb b/app/services/protected_branches/destroy_service.rb
index 47332ace417..01d3b68314f 100644
--- a/app/services/protected_branches/destroy_service.rb
+++ b/app/services/protected_branches/destroy_service.rb
@@ -5,7 +5,7 @@ module ProtectedBranches
def execute(protected_branch)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_protected_branch, protected_branch)
- protected_branch.destroy
+ protected_branch.destroy.tap { refresh_cache }
end
end
end
diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb
index 1e70f2d9793..c155e0022f5 100644
--- a/app/services/protected_branches/update_service.rb
+++ b/app/services/protected_branches/update_service.rb
@@ -10,6 +10,8 @@ module ProtectedBranches
if protected_branch.update(params)
after_execute(protected_branch: protected_branch, old_merge_access_levels: old_merge_access_levels, old_push_access_levels: old_push_access_levels)
+
+ refresh_cache
end
protected_branch