Skip to content
代码片段 群组 项目
提交 c841afbd 编辑于 作者: Dylan Griffith's avatar Dylan Griffith
浏览文件

Merge branch 'stomlinson/feature-flags-skip-load-balancing' into 'master'

Bypass load balancer during feature flag checks

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137319



Merged-by: default avatarDylan Griffith <dyl.griffith@gmail.com>
Approved-by: default avatarDylan Griffith <dyl.griffith@gmail.com>
Reviewed-by: default avatarSimon Tomlinson <stomlinson@gitlab.com>
Co-authored-by: default avatarSimon Tomlinson <stomlinson@gitlab.com>
No related branches found
No related tags found
无相关合并请求
...@@ -4,6 +4,33 @@ ...@@ -4,6 +4,33 @@
require 'flipper/adapters/active_support_cache_store' require 'flipper/adapters/active_support_cache_store'
module Feature module Feature
module BypassLoadBalancer
FLAG = 'FEATURE_FLAGS_BYPASS_LOAD_BALANCER'
class FlipperRecord < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord -- This class perfectly replaces
# Flipper::Adapters::ActiveRecord::Model, which inherits ActiveRecord::Base
include DatabaseReflection
self.abstract_class = true
# Bypass the load balancer by restoring the default behavior of `connection`
# before the load balancer patches ActiveRecord::Base
def self.connection
retrieve_connection
end
end
class FlipperFeature < FlipperRecord
self.table_name = 'features'
end
class FlipperGate < FlipperRecord
self.table_name = 'feature_gates'
end
def self.enabled?
Gitlab::Utils.to_boolean(ENV[FLAG], default: false)
end
end
# Classes to override flipper table names # Classes to override flipper table names
class FlipperFeature < Flipper::Adapters::ActiveRecord::Feature class FlipperFeature < Flipper::Adapters::ActiveRecord::Feature
include DatabaseReflection include DatabaseReflection
...@@ -70,7 +97,8 @@ def get(key) ...@@ -70,7 +97,8 @@ def get(key)
end end
def persisted_names def persisted_names
return [] unless ApplicationRecord.database.exists? model = BypassLoadBalancer.enabled? ? BypassLoadBalancer::FlipperRecord : ApplicationRecord
return [] unless model.database.exists?
# This loads names of all stored feature flags # This loads names of all stored feature flags
# and returns a stable Set in the following order: # and returns a stable Set in the following order:
...@@ -306,7 +334,9 @@ def with_feature(key) ...@@ -306,7 +334,9 @@ def with_feature(key)
def unsafe_get(key) def unsafe_get(key)
# During setup the database does not exist yet. So we haven't stored a value # During setup the database does not exist yet. So we haven't stored a value
# for the feature yet and return the default. # for the feature yet and return the default.
return unless ApplicationRecord.database.exists?
model = BypassLoadBalancer.enabled? ? BypassLoadBalancer::FlipperRecord : ApplicationRecord
return unless model.database.exists?
flag_stack = ::Thread.current[:feature_flag_recursion_check] || [] flag_stack = ::Thread.current[:feature_flag_recursion_check] || []
Thread.current[:feature_flag_recursion_check] = flag_stack Thread.current[:feature_flag_recursion_check] = flag_stack
...@@ -340,10 +370,15 @@ def flipper ...@@ -340,10 +370,15 @@ def flipper
end end
def build_flipper_instance(memoize: false) def build_flipper_instance(memoize: false)
active_record_adapter = Flipper::Adapters::ActiveRecord.new( active_record_adapter = if BypassLoadBalancer.enabled?
feature_class: FlipperFeature, Flipper::Adapters::ActiveRecord.new(
gate_class: FlipperGate) feature_class: BypassLoadBalancer::FlipperFeature,
gate_class: BypassLoadBalancer::FlipperGate)
else
Flipper::Adapters::ActiveRecord.new(
feature_class: FlipperFeature,
gate_class: FlipperGate)
end
# Redis L2 cache # Redis L2 cache
redis_cache_adapter = redis_cache_adapter =
ActiveSupportCacheStoreAdapter.new( ActiveSupportCacheStoreAdapter.new(
......
此差异已折叠。
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册