Class: Gitlab::Database::LoadBalancing::ConnectionProxy
- Inherits:
-
Object
- Object
- Gitlab::Database::LoadBalancing::ConnectionProxy
- Defined in:
- lib/gitlab/database/load_balancing/connection_proxy.rb
Overview
Redirecting of ActiveRecord connections.
The ConnectionProxy class redirects ActiveRecord connection requests to the right load balancer pool, depending on the type of query.
Constant Summary collapse
- WriteInsideReadOnlyTransactionError =
Class.new(StandardError)
- READ_ONLY_TRANSACTION_KEY =
:load_balacing_read_only_transaction
- STICKY_WRITES =
These methods perform writes after which we need to stick to the primary.
%i[ delete delete_all insert update update_all exec_insert_all ].freeze
- NON_STICKY_READS =
%i[ sanitize_limit select select_one select_rows quote_column_name ].freeze
Instance Attribute Summary collapse
-
#load_balancer ⇒ Object
readonly
Returns the value of attribute load_balancer.
Instance Method Summary collapse
-
#initialize(load_balancer) ⇒ ConnectionProxy
constructor
hosts - The hosts to use for load balancing.
-
#method_missing ⇒ Object
Delegates all unknown messages to a read-write connection.
-
#read_using_load_balancer ⇒ Object
Performs a read using the load balancer.
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
- #schema_cache(*args, **kwargs, &block) ⇒ Object
- #select_all(arel, name = nil, binds = [], preparable: nil, async: false) ⇒ Object
- #transaction(*args, **kwargs, &block) ⇒ Object
-
#write_using_load_balancer ⇒ Object
Performs a write using the load balancer.
Constructor Details
#initialize(load_balancer) ⇒ ConnectionProxy
hosts - The hosts to use for load balancing.
38 39 40 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 38 def initialize(load_balancer) @load_balancer = load_balancer end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing ⇒ Object
Delegates all unknown messages to a read-write connection.
92 93 94 95 96 97 98 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 92 def method_missing(...) if current_session.fallback_to_replicas_for_ambiguous_queries? read_using_load_balancer(...) else write_using_load_balancer(...) end end |
Instance Attribute Details
#load_balancer ⇒ Object (readonly)
Returns the value of attribute load_balancer.
16 17 18 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 16 def load_balancer @load_balancer end |
Instance Method Details
#read_using_load_balancer ⇒ Object
Performs a read using the load balancer.
name - The name of the method to call on a connection object.
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 103 def read_using_load_balancer(...) if current_session.use_primary? && !current_session.use_replicas_for_read_queries? @load_balancer.read_write do |connection| connection.public_send(...) end else @load_balancer.read do |connection| connection.public_send(...) end end end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
85 86 87 88 89 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 85 def respond_to_missing?(name, include_private = false) @load_balancer.read_write do |connection| connection.respond_to?(name, include_private) end end |
#schema_cache(*args, **kwargs, &block) ⇒ Object
65 66 67 68 69 70 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 65 def schema_cache(*args, **kwargs, &block) # Ignore primary stickiness for schema_cache queries and always use replicas @load_balancer.read do |connection| connection.public_send(:schema_cache, *args, **kwargs, &block) end end |
#select_all(arel, name = nil, binds = [], preparable: nil, async: false) ⇒ Object
42 43 44 45 46 47 48 49 50 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 42 def select_all(arel, name = nil, binds = [], preparable: nil, async: false) if arel.respond_to?(:locked) && arel.locked # SELECT ... FOR UPDATE queries should be sent to the primary. current_session.write! write_using_load_balancer(:select_all, arel, name, binds) else read_using_load_balancer(:select_all, arel, name, binds) end end |
#transaction(*args, **kwargs, &block) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 72 def transaction(*args, **kwargs, &block) if current_session.fallback_to_replicas_for_ambiguous_queries? track_read_only_transaction! read_using_load_balancer(:transaction, *args, **kwargs, &block) else current_session.write! write_using_load_balancer(:transaction, *args, **kwargs, &block) end ensure untrack_read_only_transaction! end |
#write_using_load_balancer ⇒ Object
Performs a write using the load balancer.
name - The name of the method to call on a connection object. sticky - If set to true the session will stick to the master after
the write.
121 122 123 124 125 126 127 128 129 |
# File 'lib/gitlab/database/load_balancing/connection_proxy.rb', line 121 def write_using_load_balancer(...) if read_only_transaction? raise WriteInsideReadOnlyTransactionError, 'A write query is performed inside a read-only transaction' end @load_balancer.read_write do |connection| connection.public_send(...) end end |