From aee0a117a889461ce8ced6fcf73207fe017f1d99 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 20 Dec 2021 13:37:47 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-6-stable-ee --- lib/gitlab/redis/multi_store.rb | 52 ++++++++++++++++++++----------- lib/gitlab/redis/sessions.rb | 42 +++++++++++++++++++++++-- lib/gitlab/redis/sessions_store_helper.rb | 27 ++++++++++++++++ lib/gitlab/redis/shared_state.rb | 4 --- lib/gitlab/redis/wrapper.rb | 12 ++++++- 5 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 lib/gitlab/redis/sessions_store_helper.rb (limited to 'lib/gitlab/redis') diff --git a/lib/gitlab/redis/multi_store.rb b/lib/gitlab/redis/multi_store.rb index f930a0040bc..500b62bf0e8 100644 --- a/lib/gitlab/redis/multi_store.rb +++ b/lib/gitlab/redis/multi_store.rb @@ -21,6 +21,8 @@ module Gitlab FAILED_TO_READ_ERROR_MESSAGE = 'Failed to read from the redis primary_store.' FAILED_TO_WRITE_ERROR_MESSAGE = 'Failed to write to the redis primary_store.' + SKIP_LOG_METHOD_MISSING_FOR_COMMANDS = %i(info).freeze + READ_COMMANDS = %i( get mget @@ -39,41 +41,42 @@ module Gitlab flushdb ).freeze - def initialize(primary_store, secondary_store, instance_name = nil) + def initialize(primary_store, secondary_store, instance_name) @primary_store = primary_store @secondary_store = secondary_store @instance_name = instance_name validate_stores! end - + # rubocop:disable GitlabSecurity/PublicSend READ_COMMANDS.each do |name| define_method(name) do |*args, &block| - if multi_store_enabled? + if use_primary_and_secondary_stores? read_command(name, *args, &block) else - secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend + default_store.send(name, *args, &block) end end end WRITE_COMMANDS.each do |name| define_method(name) do |*args, &block| - if multi_store_enabled? + if use_primary_and_secondary_stores? write_command(name, *args, &block) else - secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend + default_store.send(name, *args, &block) end end end def method_missing(...) - return @instance.send(...) if @instance # rubocop:disable GitlabSecurity/PublicSend + return @instance.send(...) if @instance log_method_missing(...) - secondary_store.send(...) # rubocop:disable GitlabSecurity/PublicSend + default_store.send(...) end + # rubocop:enable GitlabSecurity/PublicSend def respond_to_missing?(command_name, include_private = false) true @@ -83,23 +86,37 @@ module Gitlab # https://github.com/redis-store/redis-rack/blob/a833086ba494083b6a384a1a4e58b36573a9165d/lib/redis/rack/connection.rb#L15 # Done similarly in https://github.com/lsegal/yard/blob/main/lib/yard/templates/template.rb#L122 def is_a?(klass) - return true if klass == secondary_store.class + return true if klass == default_store.class super(klass) end alias_method :kind_of?, :is_a? def to_s - if multi_store_enabled? - primary_store.to_s - else - secondary_store.to_s - end + use_primary_and_secondary_stores? ? primary_store.to_s : default_store.to_s + end + + def use_primary_and_secondary_stores? + feature_flags_available? && + Feature.enabled?("use_primary_and_secondary_stores_for_#{instance_name.underscore}", default_enabled: :yaml) && + !same_redis_store? + end + + def use_primary_store_as_default? + feature_flags_available? && + Feature.enabled?("use_primary_store_as_default_for_#{instance_name.underscore}", default_enabled: :yaml) && + !same_redis_store? end private + def default_store + use_primary_store_as_default? ? primary_store : secondary_store + end + def log_method_missing(command_name, *_args) + return if SKIP_LOG_METHOD_MISSING_FOR_COMMANDS.include?(command_name) + log_error(MethodMissingError.new, command_name) increment_method_missing_count(command_name) end @@ -155,10 +172,6 @@ module Gitlab send_command(secondary_store, command_name, *args, &block) end - def multi_store_enabled? - Feature.enabled?(:use_multi_store, default_enabled: :yaml) && !same_redis_store? - end - def same_redis_store? strong_memoize(:same_redis_store) do # " @@ -194,12 +207,13 @@ module Gitlab def increment_method_missing_count(command_name) @method_missing_counter ||= Gitlab::Metrics.counter(:gitlab_redis_multi_store_method_missing_total, 'Client side Redis MultiStore method missing') - @method_missing_counter.increment(command: command_name, innamece_name: instance_name) + @method_missing_counter.increment(command: command_name, instance_name: instance_name) end def validate_stores! raise ArgumentError, 'primary_store is required' unless primary_store raise ArgumentError, 'secondary_store is required' unless secondary_store + raise ArgumentError, 'instance_name is required' unless instance_name raise ArgumentError, 'invalid primary_store' unless primary_store.is_a?(::Redis) raise ArgumentError, 'invalid secondary_store' unless secondary_store.is_a?(::Redis) end diff --git a/lib/gitlab/redis/sessions.rb b/lib/gitlab/redis/sessions.rb index 3bf1eb6211d..c547828d907 100644 --- a/lib/gitlab/redis/sessions.rb +++ b/lib/gitlab/redis/sessions.rb @@ -3,9 +3,45 @@ module Gitlab module Redis class Sessions < ::Gitlab::Redis::Wrapper - # The data we store on Sessions used to be stored on SharedState. - def self.config_fallback - SharedState + SESSION_NAMESPACE = 'session:gitlab' + USER_SESSIONS_NAMESPACE = 'session:user:gitlab' + USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab' + IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2' + OTP_SESSIONS_NAMESPACE = 'session:otp' + + class << self + # The data we store on Sessions used to be stored on SharedState. + def config_fallback + SharedState + end + + private + + def redis + # Don't use multistore if redis.sessions configuration is not provided + return super if config_fallback? + + primary_store = ::Redis.new(params) + secondary_store = ::Redis.new(config_fallback.params) + + MultiStore.new(primary_store, secondary_store, store_name) + end + end + + def store(extras = {}) + # Don't use multistore if redis.sessions configuration is not provided + return super if self.class.config_fallback? + + primary_store = create_redis_store(redis_store_options, extras) + secondary_store = create_redis_store(self.class.config_fallback.params, extras) + + MultiStore.new(primary_store, secondary_store, self.class.store_name) + end + + private + + def create_redis_store(options, extras) + ::Redis::Store.new(options.merge(extras)) end end end diff --git a/lib/gitlab/redis/sessions_store_helper.rb b/lib/gitlab/redis/sessions_store_helper.rb new file mode 100644 index 00000000000..c80442847f1 --- /dev/null +++ b/lib/gitlab/redis/sessions_store_helper.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Gitlab + module Redis + module SessionsStoreHelper + extend ActiveSupport::Concern + + module StoreMethods + def redis_store_class + use_redis_session_store? ? Gitlab::Redis::Sessions : Gitlab::Redis::SharedState + end + + private + + def use_redis_session_store? + Gitlab::Utils.to_boolean(ENV['GITLAB_USE_REDIS_SESSIONS_STORE'], default: true) + end + end + + include StoreMethods + + included do + extend StoreMethods + end + end + end +end diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb index 1250eabb041..fb3a143121b 100644 --- a/lib/gitlab/redis/shared_state.rb +++ b/lib/gitlab/redis/shared_state.rb @@ -3,10 +3,6 @@ module Gitlab module Redis class SharedState < ::Gitlab::Redis::Wrapper - SESSION_NAMESPACE = 'session:gitlab' - USER_SESSIONS_NAMESPACE = 'session:user:gitlab' - USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab' - IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2' end end end diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb index 985c8dc619c..75dbccb965d 100644 --- a/lib/gitlab/redis/wrapper.rb +++ b/lib/gitlab/redis/wrapper.rb @@ -28,7 +28,7 @@ module Gitlab end def pool - @pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) } + @pool ||= ConnectionPool.new(size: pool_size) { redis } end def pool_size @@ -67,6 +67,10 @@ module Gitlab File.expand_path('../../..', __dir__) end + def config_fallback? + config_file_name == config_fallback&.config_file_name + end + def config_file_name [ # Instance specific config sources: @@ -100,6 +104,12 @@ module Gitlab "::Gitlab::Instrumentation::Redis::#{store_name}".constantize end + + private + + def redis + ::Redis.new(params) + end end def initialize(rails_env = nil) -- cgit v1.2.3