active_record_shards 3.16.0 → 3.19.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,278 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordShards
4
+ module DefaultReplicaPatches
5
+ def self.wrap_method_in_on_replica(class_method, base, method, force_on_replica: false)
6
+ base_methods =
7
+ if class_method
8
+ base.methods + base.private_methods
9
+ else
10
+ base.instance_methods + base.private_instance_methods
11
+ end
12
+
13
+ return unless base_methods.include?(method)
14
+
15
+ _, method, punctuation = method.to_s.match(/^(.*?)([\?\!]?)$/).to_a
16
+ # _ALWAYS_ on replica, or only for on `on_replica_by_default = true` models?
17
+ wrapper = force_on_replica ? 'force_on_replica' : 'on_replica_unless_tx'
18
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
19
+ #{class_method ? 'class << self' : ''}
20
+ def #{method}_with_default_replica#{punctuation}(*args, &block)
21
+ #{wrapper} do
22
+ #{method}_without_default_replica#{punctuation}(*args, &block)
23
+ end
24
+ end
25
+
26
+ alias_method :#{method}_without_default_replica#{punctuation}, :#{method}#{punctuation}
27
+ alias_method :#{method}#{punctuation}, :#{method}_with_default_replica#{punctuation}
28
+ #{class_method ? 'end' : ''}
29
+ RUBY
30
+ end
31
+
32
+ def self.wrap_method_in_on_slave(*args)
33
+ ActiveRecordShards::Deprecation.deprecation_warning(
34
+ :'self.wrap_method_in_on_slave',
35
+ :'self.wrap_method_in_on_replica'
36
+ )
37
+ wrap_method_in_on_replica(*args)
38
+ end
39
+
40
+ def transaction_with_replica_off(*args, &block)
41
+ if on_replica_by_default?
42
+ begin
43
+ old_val = Thread.current[:_active_record_shards_in_tx]
44
+ Thread.current[:_active_record_shards_in_tx] = true
45
+ transaction_without_replica_off(*args, &block)
46
+ ensure
47
+ Thread.current[:_active_record_shards_in_tx] = old_val
48
+ end
49
+ else
50
+ transaction_without_replica_off(*args, &block)
51
+ end
52
+ end
53
+ alias_method :transaction_with_slave_off, :transaction_with_replica_off
54
+
55
+ module InstanceMethods
56
+ # fix ActiveRecord to do the right thing, and use our aliased quote_value
57
+ def quote_value(*args, &block)
58
+ self.class.quote_value(*args, &block)
59
+ end
60
+
61
+ def on_replica_unless_tx
62
+ self.class.on_replica_unless_tx { yield }
63
+ end
64
+ end
65
+
66
+ CLASS_REPLICA_METHODS = [
67
+ :calculate,
68
+ :count_by_sql,
69
+ :exists?,
70
+ :find,
71
+ :find_by,
72
+ :find_by_sql,
73
+ :find_every,
74
+ :find_one,
75
+ :find_some,
76
+ :get_primary_key
77
+ ].freeze
78
+
79
+ CLASS_FORCE_REPLICA_METHODS = [
80
+ :replace_bind_variable,
81
+ :replace_bind_variables,
82
+ :sanitize_sql_array,
83
+ :sanitize_sql_hash_for_assignment,
84
+ :table_exists?
85
+ ].freeze
86
+
87
+ CLASS_SLAVE_METHODS = CLASS_REPLICA_METHODS
88
+ CLASS_FORCE_SLAVE_METHODS = CLASS_FORCE_REPLICA_METHODS
89
+
90
+ def self.extended(base)
91
+ CLASS_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m) }
92
+ CLASS_FORCE_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m, force_on_replica: true) }
93
+
94
+ if ActiveRecord::VERSION::MAJOR >= 5
95
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, :load_schema!, force_on_replica: true)
96
+ else
97
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, :columns, force_on_replica: true)
98
+ end
99
+
100
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :reload)
101
+
102
+ base.class_eval do
103
+ include InstanceMethods
104
+
105
+ class << self
106
+ alias_method :transaction_without_replica_off, :transaction
107
+ alias_method :transaction, :transaction_with_replica_off
108
+ end
109
+ end
110
+ end
111
+
112
+ def on_replica_unless_tx(&block)
113
+ return yield if Thread.current[:_active_record_shards_in_migration]
114
+ return yield if Thread.current[:_active_record_shards_in_tx]
115
+
116
+ if on_replica_by_default?
117
+ on_replica(&block)
118
+ else
119
+ yield
120
+ end
121
+ end
122
+ alias_method :on_slave_unless_tx, :on_replica_unless_tx
123
+
124
+ def force_on_replica(&block)
125
+ return yield if Thread.current[:_active_record_shards_in_migration]
126
+
127
+ on_cx_switch_block(:replica, construct_ro_scope: false, force: true, &block)
128
+ end
129
+
130
+ module ActiveRelationPatches
131
+ def self.included(base)
132
+ [:calculate, :exists?, :pluck, :load].each do |m|
133
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, m)
134
+ end
135
+
136
+ if ActiveRecord::VERSION::MAJOR == 4
137
+ # `where` and `having` clauses call `create_binds`, which will use the primary connection
138
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :create_binds, force_on_replica: true)
139
+ end
140
+
141
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :to_sql, force_on_replica: true)
142
+ end
143
+
144
+ def on_replica_unless_tx
145
+ @klass.on_replica_unless_tx { yield }
146
+ end
147
+ end
148
+
149
+ module Rails52RelationPatches
150
+ def connection
151
+ return super if Thread.current[:_active_record_shards_in_migration]
152
+ return super if Thread.current[:_active_record_shards_in_tx]
153
+
154
+ if @klass.on_replica_by_default?
155
+ @klass.on_replica.connection
156
+ else
157
+ super
158
+ end
159
+ end
160
+ end
161
+
162
+ # in rails 4.1+, they create a join class that's used to pull in records for HABTM.
163
+ # this simplifies the hell out of our existence, because all we have to do is inerit on-replica-by-default
164
+ # down from the parent now.
165
+ module Rails41HasAndBelongsToManyBuilderExtension
166
+ def self.included(base)
167
+ base.class_eval do
168
+ alias_method :through_model_without_inherit_default_replica_from_lhs, :through_model
169
+ alias_method :through_model, :through_model_with_inherit_default_replica_from_lhs
170
+ end
171
+ end
172
+
173
+ def through_model_with_inherit_default_replica_from_lhs
174
+ model = through_model_without_inherit_default_replica_from_lhs
175
+ def model.on_replica_by_default?
176
+ left_reflection.klass.on_replica_by_default?
177
+ end
178
+
179
+ # also transfer the sharded-ness of the left table to the join model
180
+ model.not_sharded unless model.left_reflection.klass.is_sharded?
181
+ model
182
+ end
183
+ end
184
+
185
+ module AssociationsAssociationAssociationScopePatch
186
+ def association_scope
187
+ if klass
188
+ on_replica_unless_tx { super }
189
+ else
190
+ super
191
+ end
192
+ end
193
+
194
+ def on_replica_unless_tx
195
+ klass.on_replica_unless_tx { yield }
196
+ end
197
+ end
198
+
199
+ module AssociationsAssociationFindTargetPatch
200
+ def find_target
201
+ if klass
202
+ on_replica_unless_tx { super }
203
+ else
204
+ super
205
+ end
206
+ end
207
+
208
+ def on_replica_unless_tx
209
+ klass.on_replica_unless_tx { yield }
210
+ end
211
+ end
212
+
213
+ module AssociationsAssociationGetRecordsPatch
214
+ def get_records # rubocop:disable Naming/AccessorMethodName
215
+ if klass
216
+ on_replica_unless_tx { super }
217
+ else
218
+ super
219
+ end
220
+ end
221
+
222
+ def on_replica_unless_tx
223
+ klass.on_replica_unless_tx { yield }
224
+ end
225
+ end
226
+
227
+ module AssociationsPreloaderAssociationAssociatedRecordsByOwnerPatch
228
+ def associated_records_by_owner(preloader)
229
+ if klass
230
+ on_replica_unless_tx { super }
231
+ else
232
+ super
233
+ end
234
+ end
235
+
236
+ def on_replica_unless_tx
237
+ klass.on_replica_unless_tx { yield }
238
+ end
239
+ end
240
+
241
+ module AssociationsPreloaderAssociationLoadRecordsPatch
242
+ def load_records
243
+ if klass
244
+ on_replica_unless_tx { super }
245
+ else
246
+ super
247
+ end
248
+ end
249
+
250
+ def on_replica_unless_tx
251
+ klass.on_replica_unless_tx { yield }
252
+ end
253
+ end
254
+
255
+ module TypeCasterConnectionConnectionPatch
256
+ def connection
257
+ return super if Thread.current[:_active_record_shards_in_migration]
258
+ return super if Thread.current[:_active_record_shards_in_tx]
259
+
260
+ if @klass.on_replica_by_default?
261
+ @klass.on_replica.connection
262
+ else
263
+ super
264
+ end
265
+ end
266
+ end
267
+
268
+ module SchemaDefinePatch
269
+ def define(info, &block)
270
+ old_val = Thread.current[:_active_record_shards_in_migration]
271
+ Thread.current[:_active_record_shards_in_migration] = true
272
+ super
273
+ ensure
274
+ Thread.current[:_active_record_shards_in_migration] = old_val
275
+ end
276
+ end
277
+ end
278
+ end
@@ -1,142 +1,5 @@
1
- # frozen_string_literal: true
2
- module ActiveRecordShards
3
- module DefaultSlavePatches
4
- def self.wrap_method_in_on_slave(class_method, base, method, force_on_slave: false)
5
- base_methods =
6
- if class_method
7
- base.methods + base.private_methods
8
- else
9
- base.instance_methods + base.private_instance_methods
10
- end
11
-
12
- return unless base_methods.include?(method)
13
- _, method, punctuation = method.to_s.match(/^(.*?)([\?\!]?)$/).to_a
14
- # _ALWAYS_ on slave, or only for on `on_slave_by_default = true` models?
15
- wrapper = force_on_slave ? 'force_on_slave' : 'on_slave_unless_tx'
16
- base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
17
- #{class_method ? 'class << self' : ''}
18
- def #{method}_with_default_slave#{punctuation}(*args, &block)
19
- #{wrapper} do
20
- #{method}_without_default_slave#{punctuation}(*args, &block)
21
- end
22
- end
23
-
24
- alias_method :#{method}_without_default_slave#{punctuation}, :#{method}#{punctuation}
25
- alias_method :#{method}#{punctuation}, :#{method}_with_default_slave#{punctuation}
26
- #{class_method ? 'end' : ''}
27
- RUBY
28
- end
29
-
30
- def transaction_with_slave_off(*args, &block)
31
- if on_slave_by_default?
32
- begin
33
- old_val = Thread.current[:_active_record_shards_slave_off]
34
- Thread.current[:_active_record_shards_slave_off] = true
35
- transaction_without_slave_off(*args, &block)
36
- ensure
37
- Thread.current[:_active_record_shards_slave_off] = old_val
38
- end
39
- else
40
- transaction_without_slave_off(*args, &block)
41
- end
42
- end
43
-
44
- module InstanceMethods
45
- # fix ActiveRecord to do the right thing, and use our aliased quote_value
46
- def quote_value(*args, &block)
47
- self.class.quote_value(*args, &block)
48
- end
49
- end
50
-
51
- CLASS_SLAVE_METHODS = [
52
- :calculate,
53
- :count_by_sql,
54
- :exists?,
55
- :find_by_sql,
56
- :find_every,
57
- :find_one,
58
- :find_some
59
- ].freeze
60
-
61
- CLASS_FORCE_SLAVE_METHODS = [
62
- :columns,
63
- :replace_bind_variable,
64
- :replace_bind_variables,
65
- :sanitize_sql_array,
66
- :sanitize_sql_hash_for_assignment,
67
- :table_exists?
68
- ].freeze
69
-
70
- def self.extended(base)
71
- CLASS_SLAVE_METHODS.each { |m| ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(true, base, m) }
72
- CLASS_FORCE_SLAVE_METHODS.each { |m| ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(true, base, m, force_on_slave: true) }
73
-
74
- base.class_eval do
75
- include InstanceMethods
76
-
77
- class << self
78
- alias_method :transaction_without_slave_off, :transaction
79
- alias_method :transaction, :transaction_with_slave_off
80
- end
81
- end
82
- if ActiveRecord::Associations.const_defined?(:HasAndBelongsToManyAssociation)
83
- ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_sql)
84
- ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_find_options!)
85
- end
86
- end
1
+ ActiveRecordShards::Deprecation.warn('`DefaultSlavePatches` is deprecated, please use `DefaultReplicaPatches`.')
87
2
 
88
- def on_slave_unless_tx(&block)
89
- if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
90
- on_slave(&block)
91
- else
92
- yield
93
- end
94
- end
95
-
96
- def force_on_slave(&block)
97
- on_cx_switch_block(:slave, construct_ro_scope: false, force: true, &block)
98
- end
99
-
100
- module ActiveRelationPatches
101
- def self.included(base)
102
- [:calculate, :exists?, :pluck, :load].each do |m|
103
- ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, base, m)
104
- end
105
-
106
- if ActiveRecord::VERSION::MAJOR == 4
107
- # `where` and `having` clauses call `create_binds`, which will use the master connection
108
- ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, base, :create_binds, force_on_slave: true)
109
- end
110
-
111
- ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, base, :to_sql, force_on_slave: true)
112
- end
113
-
114
- def on_slave_unless_tx(&block)
115
- @klass.on_slave_unless_tx(&block)
116
- end
117
- end
118
-
119
- # in rails 4.1+, they create a join class that's used to pull in records for HABTM.
120
- # this simplifies the hell out of our existence, because all we have to do is inerit on-slave-by-default
121
- # down from the parent now.
122
- module Rails41HasAndBelongsToManyBuilderExtension
123
- def self.included(base)
124
- base.class_eval do
125
- alias_method :through_model_without_inherit_default_slave_from_lhs, :through_model
126
- alias_method :through_model, :through_model_with_inherit_default_slave_from_lhs
127
- end
128
- end
129
-
130
- def through_model_with_inherit_default_slave_from_lhs
131
- model = through_model_without_inherit_default_slave_from_lhs
132
- def model.on_slave_by_default?
133
- left_reflection.klass.on_slave_by_default?
134
- end
135
-
136
- # also transfer the sharded-ness of the left table to the join model
137
- model.not_sharded unless model.left_reflection.klass.is_sharded?
138
- model
139
- end
140
- end
141
- end
3
+ module ActiveRecordShards
4
+ DefaultSlavePatches = DefaultReplicaPatches
142
5
  end
@@ -0,0 +1,12 @@
1
+ module ActiveRecordShards
2
+ class Deprecation < ActiveSupport::Deprecation
3
+ # This allows us to define separate deprecation behavior for ActiveRecordShards, but defaults to
4
+ # the same behavior globally configured with ActiveSupport.
5
+ #
6
+ # For example, this allows us to silence our own deprecation warnings in test while still being
7
+ # able to fail tests for upstream deprecation warnings.
8
+ def behavior
9
+ @behavior ||= ActiveSupport::Deprecation.behavior
10
+ end
11
+ end
12
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ActiveRecord
3
4
  class Migrator
4
5
  def self.shards_migration_context
@@ -6,6 +6,7 @@ module ActiveRecordShards
6
6
  if self != ActiveRecord::Base && self != base_class
7
7
  raise "You should only call not_sharded on direct descendants of ActiveRecord::Base"
8
8
  end
9
+
9
10
  self.sharded = false
10
11
  end
11
12
 
@@ -23,34 +24,38 @@ module ActiveRecordShards
23
24
  end
24
25
  end
25
26
 
26
- def on_slave_by_default?
27
+ def on_replica_by_default?
27
28
  if self == ActiveRecord::Base
28
29
  false
29
30
  else
30
31
  base = base_class
31
- if base.instance_variable_defined?(:@on_slave_by_default)
32
- base.instance_variable_get(:@on_slave_by_default)
32
+ if base.instance_variable_defined?(:@on_replica_by_default)
33
+ base.instance_variable_get(:@on_replica_by_default)
33
34
  end
34
35
  end
35
36
  end
37
+ alias_method :on_slave_by_default?, :on_replica_by_default?
36
38
 
37
- def on_slave_by_default=(value)
39
+ def on_replica_by_default=(value)
38
40
  if self == ActiveRecord::Base
39
- raise ArgumentError, "Cannot set on_slave_by_default on ActiveRecord::Base"
41
+ raise ArgumentError, "Cannot set on_replica_by_default on ActiveRecord::Base"
40
42
  else
41
- base_class.instance_variable_set(:@on_slave_by_default, value)
43
+ base_class.instance_variable_set(:@on_replica_by_default, value)
42
44
  end
43
45
  end
46
+ alias_method :on_slave_by_default=, :on_replica_by_default=
44
47
 
45
48
  module InstanceMethods
46
- def initialize_shard_and_slave
47
- @from_slave = !!self.class.current_shard_selection.options[:slave]
49
+ def initialize_shard_and_replica
50
+ @from_replica = !!self.class.current_shard_selection.options[:replica]
48
51
  @from_shard = self.class.current_shard_selection.options[:shard]
49
52
  end
53
+ alias_method :initialize_shard_and_slave, :initialize_shard_and_replica
50
54
 
51
- def from_slave?
52
- @from_slave
55
+ def from_replica?
56
+ @from_replica
53
57
  end
58
+ alias_method :from_slave?, :from_replica?
54
59
 
55
60
  def from_shard
56
61
  @from_shard
@@ -59,7 +64,7 @@ module ActiveRecordShards
59
64
 
60
65
  def self.extended(base)
61
66
  base.send(:include, InstanceMethods)
62
- base.after_initialize :initialize_shard_and_slave
67
+ base.after_initialize :initialize_shard_and_replica
63
68
  end
64
69
 
65
70
  private
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'active_record_shards/connection_pool'
3
4
  require 'active_record_shards/connection_handler'
4
5
  require 'active_record_shards/connection_specification'
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ActiveRecordShards
3
4
  module SchemaDumperExtension
4
5
  def dump(stream)
@@ -23,15 +24,15 @@ module ActiveRecordShards
23
24
  def shard_header(stream)
24
25
  define_params = @version ? "version: #{@version}" : ""
25
26
 
26
- stream.puts <<HEADER
27
+ stream.puts <<~HEADER
27
28
 
28
29
 
29
- # This section generated by active_record_shards
30
+ # This section generated by active_record_shards
30
31
 
31
- ActiveRecord::Base.on_all_shards do
32
- ActiveRecord::Schema.define(#{define_params}) do
32
+ ActiveRecord::Base.on_all_shards do
33
+ ActiveRecord::Schema.define(#{define_params}) do
33
34
 
34
- HEADER
35
+ HEADER
35
36
  end
36
37
 
37
38
  def shard_trailer(stream)
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ActiveRecordShards
3
4
  class ShardSelection
4
5
  NO_SHARD = :_no_shard
5
6
  cattr_accessor :default_shard
6
7
 
7
8
  def initialize
8
- @on_slave = false
9
+ @on_replica = false
9
10
  @shard = nil
10
11
  end
11
12
 
@@ -21,17 +22,17 @@ module ActiveRecordShards
21
22
  end
22
23
  end
23
24
 
24
- def shard_name(klass = nil, try_slave = true)
25
+ def shard_name(klass = nil, try_replica = true)
25
26
  the_shard = shard(klass)
26
27
 
27
28
  @shard_names ||= {}
28
29
  @shard_names[ActiveRecordShards.rails_env] ||= {}
29
30
  @shard_names[ActiveRecordShards.rails_env][the_shard] ||= {}
30
- @shard_names[ActiveRecordShards.rails_env][the_shard][try_slave] ||= {}
31
- @shard_names[ActiveRecordShards.rails_env][the_shard][try_slave][@on_slave] ||= begin
31
+ @shard_names[ActiveRecordShards.rails_env][the_shard][try_replica] ||= {}
32
+ @shard_names[ActiveRecordShards.rails_env][the_shard][try_replica][@on_replica] ||= begin
32
33
  s = ActiveRecordShards.rails_env.dup
33
34
  s << "_shard_#{the_shard}" if the_shard
34
- s << "_slave" if @on_slave && try_slave
35
+ s << "_replica" if @on_replica && try_replica
35
36
  s
36
37
  end
37
38
  end
@@ -46,7 +47,7 @@ module ActiveRecordShards
46
47
  end
47
48
  end
48
49
 
49
- PRIMARY = "primary".freeze
50
+ PRIMARY = "primary"
50
51
  def resolve_connection_name(sharded:, configurations:)
51
52
  resolved_shard = sharded ? shard : nil
52
53
  env = ActiveRecordShards.rails_env
@@ -54,11 +55,11 @@ module ActiveRecordShards
54
55
  @connection_names ||= {}
55
56
  @connection_names[env] ||= {}
56
57
  @connection_names[env][resolved_shard] ||= {}
57
- @connection_names[env][resolved_shard][@on_slave] ||= begin
58
+ @connection_names[env][resolved_shard][@on_replica] ||= begin
58
59
  name = env.dup
59
60
  name << "_shard_#{resolved_shard}" if resolved_shard
60
- if @on_slave && configurations["#{name}_slave"]
61
- "#{name}_slave"
61
+ if @on_replica && configurations["#{name}_replica"]
62
+ "#{name}_replica"
62
63
  else
63
64
  # ActiveRecord always names its default connection pool 'primary'
64
65
  # while everything else is named by the configuration name
@@ -73,16 +74,18 @@ module ActiveRecordShards
73
74
  @shard = (new_shard || NO_SHARD)
74
75
  end
75
76
 
76
- def on_slave?
77
- @on_slave
77
+ def on_replica?
78
+ @on_replica
78
79
  end
80
+ alias_method :on_slave?, :on_replica?
79
81
 
80
- def on_slave=(new_slave)
81
- @on_slave = (new_slave == true)
82
+ def on_replica=(new_replica)
83
+ @on_replica = (new_replica == true)
82
84
  end
85
+ alias_method :on_slave=, :on_replica=
83
86
 
84
87
  def options
85
- { shard: @shard, slave: @on_slave }
88
+ { shard: @shard, replica: @on_replica }
86
89
  end
87
90
  end
88
91
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ActiveRecordShards
3
4
  class ShardSupport
4
5
  class ShardEnumerator
@@ -1,16 +1,19 @@
1
- # show which connection was picked to debug master/slave slowness when both servers are the same
1
+ # show which connection was picked to debug primary/replica slowness when both servers are the same
2
2
  module ActiveRecordShards
3
3
  module SqlComments
4
4
  module Methods
5
5
  def execute(query, name = nil)
6
- slave = ActiveRecord::Base.current_shard_selection.on_slave?
7
- query += " /* #{slave ? 'slave' : 'master'} */"
6
+ shard = ActiveRecord::Base.current_shard_selection.shard
7
+ shard_text = shard ? "shard #{shard}" : 'unsharded'
8
+ replica = ActiveRecord::Base.current_shard_selection.on_replica?
9
+ replica_text = replica ? 'replica' : 'primary'
10
+ query = "/* #{shard_text} #{replica_text} */ " + query
8
11
  super(query, name)
9
12
  end
10
13
  end
11
14
 
12
15
  def self.enable
13
- ActiveRecord::Base.on_slave do
16
+ ActiveRecord::Base.on_replica do
14
17
  ActiveRecord::Base.on_shard(nil) do
15
18
  ActiveRecord::Base.connection.class.prepend(Methods)
16
19
  end