diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-07 21:09:16 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-07 21:09:16 +0300 |
commit | 38e6d9291369e346f33f52a5ab656b787ce0a2c0 (patch) | |
tree | c5137121d6cc0ff5d9372252569c10a05164b794 /lib/gitlab/instrumentation | |
parent | 2a501f63df96252295df7efe53880c5e78fa22b5 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/instrumentation')
-rw-r--r-- | lib/gitlab/instrumentation/redis_base.rb | 22 | ||||
-rw-r--r-- | lib/gitlab/instrumentation/redis_cluster_validator.rb | 15 |
2 files changed, 27 insertions, 10 deletions
diff --git a/lib/gitlab/instrumentation/redis_base.rb b/lib/gitlab/instrumentation/redis_base.rb index 91ee5885ed2..4f27fce43a4 100644 --- a/lib/gitlab/instrumentation/redis_base.rb +++ b/lib/gitlab/instrumentation/redis_base.rb @@ -5,6 +5,8 @@ require 'redis' module Gitlab module Instrumentation class RedisBase + VALIDATE_ALLOWED_COMMANDS_KEY = 'validate_allowed_commands_flag' + class << self include ::Gitlab::Utils::StrongMemoize include ::Gitlab::Instrumentation::RedisPayload @@ -75,13 +77,23 @@ module Gitlab query_time.round(::Gitlab::InstrumentationHelper::DURATION_PRECISION) end + def validate_allowed_commands? + ::Gitlab::SafeRequestStore.fetch(VALIDATE_ALLOWED_COMMANDS_KEY) do + Feature.enabled?(:validate_allowed_cross_slot_commands, type: :development) + end + end + def redis_cluster_validate!(commands) - ::Gitlab::Instrumentation::RedisClusterValidator.validate!(commands) if @redis_cluster_validation - true - rescue ::Gitlab::Instrumentation::RedisClusterValidator::CrossSlotError - raise if Rails.env.development? || Rails.env.test? # raise in test environments to catch violations + return true unless @redis_cluster_validation + + result = ::Gitlab::Instrumentation::RedisClusterValidator.validate(commands, validate_allowed_commands?) + return true if result.nil? + + if !result[:valid] && !result[:allowed] && (Rails.env.development? || Rails.env.test?) + raise RedisClusterValidator::CrossSlotError, "Redis command #{result[:command_name]} arguments hash to different slots. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands" + end - false + result[:valid] end def enable_redis_cluster_validation diff --git a/lib/gitlab/instrumentation/redis_cluster_validator.rb b/lib/gitlab/instrumentation/redis_cluster_validator.rb index a928d626f38..ad715574ec2 100644 --- a/lib/gitlab/instrumentation/redis_cluster_validator.rb +++ b/lib/gitlab/instrumentation/redis_cluster_validator.rb @@ -183,8 +183,8 @@ module Gitlab CrossSlotError = Class.new(StandardError) class << self - def validate!(commands) - return if allow_cross_slot_commands? + def validate(commands, validate_allowed_cmd) + return if allow_cross_slot_commands? && !validate_allowed_cmd return if commands.empty? # early exit for single-command (non-pipelined) if it is a single-key-command @@ -192,9 +192,14 @@ module Gitlab return if commands.size == 1 && REDIS_COMMANDS.dig(command_name, :single_key) key_slots = commands.map { |command| key_slots(command) }.flatten - if key_slots.uniq.many? # rubocop: disable CodeReuse/ActiveRecord - raise CrossSlotError, "Redis command #{command_name} arguments hash to different slots. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands" - end + + { + valid: !key_slots.uniq.many?, # rubocop: disable CodeReuse/ActiveRecord + command_name: command_name, + key_count: key_slots.size, + allowed: allow_cross_slot_commands?, + command: commands.first.join(' ') + } end # Keep track of the call stack to allow nested calls to work. |