active_record_shards 3.22.0 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,34 +1,16 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require 'active_record_shards/shard_support'
4
3
 
5
4
  module ActiveRecordShards
6
5
  module ConnectionSwitcher
7
- SHARD_NAMES_CONFIG_KEY = 'shard_names'
6
+ SHARD_NAMES_CONFIG_KEY = 'shard_names'.freeze
8
7
 
9
8
  def self.extended(base)
10
- if ActiveRecord::VERSION::MAJOR >= 5
11
- base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!)
12
- base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!)
13
- else
14
- base.singleton_class.send(:alias_method, :columns_without_default_shard, :columns)
15
- base.singleton_class.send(:alias_method, :columns, :columns_with_default_shard)
16
- end
9
+ base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!)
10
+ base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!)
17
11
 
18
12
  base.singleton_class.send(:alias_method, :table_exists_without_default_shard?, :table_exists?)
19
13
  base.singleton_class.send(:alias_method, :table_exists?, :table_exists_with_default_shard?)
20
-
21
- base.singleton_class.send(:alias_method, :reset_primary_key_without_default_shard, :reset_primary_key)
22
- base.singleton_class.send(:alias_method, :reset_primary_key, :reset_primary_key_with_default_shard)
23
- end
24
-
25
- def default_shard=(new_default_shard)
26
- ActiveRecordShards::ShardSelection.default_shard = new_default_shard
27
- switch_connection(shard: new_default_shard)
28
- end
29
-
30
- def on_primary_db(&block)
31
- on_shard(nil, &block)
32
14
  end
33
15
 
34
16
  def on_shard(shard)
@@ -39,9 +21,9 @@ module ActiveRecordShards
39
21
  switch_connection(old_options)
40
22
  end
41
23
 
42
- def on_first_shard(&block)
24
+ def on_first_shard
43
25
  shard_name = shard_names.first
44
- on_shard(shard_name, &block)
26
+ on_shard(shard_name) { yield }
45
27
  end
46
28
 
47
29
  def shards
@@ -62,93 +44,88 @@ module ActiveRecordShards
62
44
  switch_connection(old_options)
63
45
  end
64
46
 
65
- def on_replica_if(condition, &block)
66
- condition ? on_replica(&block) : yield
47
+ def on_slave_if(condition, &block)
48
+ condition ? on_slave(&block) : yield
67
49
  end
68
- alias_method :on_slave_if, :on_replica_if
69
50
 
70
- def on_replica_unless(condition, &block)
71
- on_replica_if(!condition, &block)
51
+ def on_slave_unless(condition, &block)
52
+ on_slave_if(!condition, &block)
72
53
  end
73
- alias_method :on_slave_unless, :on_replica_unless
74
54
 
75
- def on_primary_if(condition, &block)
76
- condition ? on_primary(&block) : yield
55
+ def on_master_if(condition, &block)
56
+ condition ? on_master(&block) : yield
77
57
  end
78
- alias_method :on_master_if, :on_primary_if
79
58
 
80
- def on_primary_unless(condition, &block)
81
- on_primary_if(!condition, &block)
59
+ def on_master_unless(condition, &block)
60
+ on_master_if(!condition, &block)
82
61
  end
83
- alias_method :on_master_unless, :on_primary_unless
84
62
 
85
- def on_primary_or_replica(which, &block)
63
+ def on_master_or_slave(which, &block)
86
64
  if block_given?
87
65
  on_cx_switch_block(which, &block)
88
66
  else
89
- PrimaryReplicaProxy.new(self, which)
67
+ MasterSlaveProxy.new(self, which)
90
68
  end
91
69
  end
92
- alias_method :on_master_or_slave, :on_primary_or_replica
93
70
 
94
- # Executes queries using the replica database. Fails over to primary if no replica is found.
95
- # if you want to execute a block of code on the replica you can go:
96
- # Account.on_replica do
71
+ # Executes queries using the slave database. Fails over to master if no slave is found.
72
+ # if you want to execute a block of code on the slave you can go:
73
+ # Account.on_slave do
97
74
  # Account.first
98
75
  # end
99
- # the first account will be found on the replica DB
76
+ # the first account will be found on the slave DB
100
77
  #
101
78
  # For one-liners you can simply do
102
- # Account.on_replica.first
103
- def on_replica(&block)
104
- on_primary_or_replica(:replica, &block)
79
+ # Account.on_slave.first
80
+ def on_slave(&block)
81
+ on_master_or_slave(:slave, &block)
105
82
  end
106
- alias_method :on_slave, :on_replica
107
83
 
108
- def on_primary(&block)
109
- on_primary_or_replica(:primary, &block)
84
+ def on_master(&block)
85
+ on_master_or_slave(:master, &block)
110
86
  end
111
- alias_method :on_master, :on_primary
112
-
113
- # just to ease the transition from replica to active_record_shards
114
- alias_method :with_slave, :on_replica
115
- alias_method :with_slave_if, :on_replica_if
116
- alias_method :with_slave_unless, :on_replica_unless
117
87
 
118
88
  def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block)
119
- @disallow_replica ||= 0
120
- @disallow_replica += 1 if [:primary, :master].include?(which)
89
+ @disallow_slave ||= 0
90
+ @disallow_slave += 1 if which == :master
121
91
 
122
- ActiveRecordShards::Deprecation.warn('the `:master` option should be replaced with `:primary`!') if which == :master
123
-
124
- switch_to_replica = force || @disallow_replica.zero?
92
+ switch_to_slave = force || @disallow_slave.zero?
125
93
  old_options = current_shard_selection.options
126
94
 
127
- switch_connection(replica: switch_to_replica)
95
+ switch_connection(slave: switch_to_slave)
128
96
 
129
97
  # we avoid_readonly_scope to prevent some stack overflow problems, like when
130
98
  # .columns calls .with_scope which calls .columns and onward, endlessly.
131
- if self == ActiveRecord::Base || !switch_to_replica || construct_ro_scope == false || ActiveRecordShards.disable_replica_readonly_records == true
99
+ if self == ActiveRecord::Base || !switch_to_slave || construct_ro_scope == false
132
100
  yield
133
101
  else
134
102
  readonly.scoping(&block)
135
103
  end
136
104
  ensure
137
- @disallow_replica -= 1 if [:primary, :master].include?(which)
105
+ @disallow_slave -= 1 if which == :master
138
106
  switch_connection(old_options) if old_options
139
107
  end
140
108
 
109
+ def connection_specification_name
110
+ name = current_shard_selection.resolve_connection_name(sharded: is_sharded?, configurations: configurations)
111
+
112
+ unless configurations[name] || name == "primary"
113
+ raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.inspect})"
114
+ end
115
+
116
+ name
117
+ end
118
+
141
119
  def supports_sharding?
142
120
  shard_names.any?
143
121
  end
144
122
 
145
- def on_replica?
146
- current_shard_selection.on_replica?
123
+ def on_slave?
124
+ current_shard_selection.on_slave?
147
125
  end
148
- alias_method :on_slave?, :on_replica?
149
126
 
150
127
  def current_shard_selection
151
- Thread.current[:shard_selection] ||= ShardSelection.new
128
+ Thread.current[:shard_selection] ||= ShardSelection.new(shard_names.first)
152
129
  end
153
130
 
154
131
  def current_shard_id
@@ -156,99 +133,78 @@ module ActiveRecordShards
156
133
  end
157
134
 
158
135
  def shard_names
159
- unless config_for_env.fetch(SHARD_NAMES_CONFIG_KEY, []).all? { |shard_name| shard_name.is_a?(Integer) }
160
- raise "All shard names must be integers: #{config_for_env[SHARD_NAMES_CONFIG_KEY].inspect}."
136
+ unless config = configurations[shard_env]
137
+ raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.inspect})"
161
138
  end
162
-
163
- config_for_env[SHARD_NAMES_CONFIG_KEY] || []
164
- end
165
-
166
- def reset_primary_key_with_default_shard
167
- with_default_shard { reset_primary_key_without_default_shard }
139
+ unless config[SHARD_NAMES_CONFIG_KEY]
140
+ raise "No shards configured for #{shard_env}"
141
+ end
142
+ unless config[SHARD_NAMES_CONFIG_KEY].all? { |shard_name| shard_name.is_a?(Integer) }
143
+ raise "All shard names must be integers: #{config[SHARD_NAMES_CONFIG_KEY].inspect}."
144
+ end
145
+ config[SHARD_NAMES_CONFIG_KEY]
168
146
  end
169
147
 
170
148
  private
171
149
 
172
- def config_for_env
173
- @_ars_config_for_env ||= {}
174
- @_ars_config_for_env[shard_env] ||= begin
175
- unless config = configurations[shard_env]
176
- raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.to_h.keys.inspect})"
177
- end
178
-
179
- config
180
- end
181
- end
182
- alias_method :check_config_for_env, :config_for_env
183
-
184
150
  def switch_connection(options)
185
151
  if options.any?
186
- if options.key?(:replica)
187
- current_shard_selection.on_replica = options[:replica]
188
- end
189
-
190
152
  if options.key?(:shard)
191
- check_config_for_env
192
-
153
+ unless config = configurations[shard_env]
154
+ raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.inspect})"
155
+ end
156
+ unless config['shard_names'].include?(options[:shard])
157
+ raise "Did not find shard #{options[:shard]} in configurations"
158
+ end
193
159
  current_shard_selection.shard = options[:shard]
194
160
  end
195
161
 
162
+ if options.key?(:slave)
163
+ current_shard_selection.on_slave = options[:slave]
164
+ end
165
+
196
166
  ensure_shard_connection
197
167
  end
198
168
  end
199
169
 
200
170
  def shard_env
201
- ActiveRecordShards.app_env
171
+ ActiveRecordShards.rails_env
202
172
  end
203
173
 
204
- # Make these few schema related methods available before having switched to
205
- # a shard.
206
- def with_default_shard(&block)
174
+ def with_default_shard
207
175
  if is_sharded? && current_shard_id.nil? && table_name != ActiveRecord::SchemaMigration.table_name
208
- on_first_shard(&block)
176
+ on_first_shard { yield }
209
177
  else
210
178
  yield
211
179
  end
212
180
  end
213
181
 
214
- if ActiveRecord::VERSION::MAJOR >= 5
215
- def load_schema_with_default_shard!
216
- with_default_shard { load_schema_without_default_shard! }
217
- end
218
- else
219
- def columns_with_default_shard
220
- with_default_shard { columns_without_default_shard }
221
- end
182
+ def load_schema_with_default_shard!
183
+ with_default_shard { load_schema_without_default_shard! }
222
184
  end
223
185
 
224
186
  def table_exists_with_default_shard?
225
187
  with_default_shard { table_exists_without_default_shard? }
226
188
  end
227
189
 
228
- class PrimaryReplicaProxy
190
+ class MasterSlaveProxy
229
191
  def initialize(target, which)
230
192
  @target = target
231
193
  @which = which
232
194
  end
233
195
 
234
- def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
235
- @target.on_primary_or_replica(@which) { @target.send(method, *args, &block) }
196
+ def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissing
197
+ @target.on_master_or_slave(@which) { @target.send(method, *args, &block) }
236
198
  end
237
199
  end
238
-
239
- MasterSlaveProxy = PrimaryReplicaProxy
240
200
  end
241
201
  end
242
202
 
243
203
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
244
- when '4.2'
245
- require 'active_record_shards/connection_switcher-4-2'
246
204
  when '5.0'
247
205
  require 'active_record_shards/connection_switcher-5-0'
248
- when '5.1', '5.2'
206
+ when '5.1'
249
207
  require 'active_record_shards/connection_switcher-5-1'
250
- when '6.0'
251
- require 'active_record_shards/connection_switcher-6-0'
252
208
  else
253
209
  raise "ActiveRecordShards is not compatible with #{ActiveRecord::VERSION::STRING}"
254
210
  end
@@ -1,5 +1,136 @@
1
- ActiveRecordShards::Deprecation.warn('`DefaultSlavePatches` is deprecated, please use `DefaultReplicaPatches`.')
2
-
1
+ # frozen_string_literal: true
3
2
  module ActiveRecordShards
4
- DefaultSlavePatches = DefaultReplicaPatches
3
+ module DefaultSlavePatches
4
+ def self.wrap_method_in_on_slave(class_method, base, method)
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
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
15
+ #{class_method ? 'class << self' : ''}
16
+ def #{method}_with_default_slave#{punctuation}(*args, &block)
17
+ on_slave_unless_tx do
18
+ #{method}_without_default_slave#{punctuation}(*args, &block)
19
+ end
20
+ end
21
+
22
+ alias_method :#{method}_without_default_slave#{punctuation}, :#{method}#{punctuation}
23
+ alias_method :#{method}#{punctuation}, :#{method}_with_default_slave#{punctuation}
24
+ #{class_method ? 'end' : ''}
25
+ RUBY
26
+ end
27
+
28
+ def columns_with_force_slave(*args, &block)
29
+ on_cx_switch_block(:slave, construct_ro_scope: false, force: true) do
30
+ columns_without_force_slave(*args, &block)
31
+ end
32
+ end
33
+
34
+ def table_exists_with_force_slave?(*args, &block)
35
+ on_cx_switch_block(:slave, construct_ro_scope: false, force: true) do
36
+ table_exists_without_force_slave?(*args, &block)
37
+ end
38
+ end
39
+
40
+ def transaction_with_slave_off(*args, &block)
41
+ if on_slave_by_default?
42
+ begin
43
+ old_val = Thread.current[:_active_record_shards_slave_off]
44
+ Thread.current[:_active_record_shards_slave_off] = true
45
+ transaction_without_slave_off(*args, &block)
46
+ ensure
47
+ Thread.current[:_active_record_shards_slave_off] = old_val
48
+ end
49
+ else
50
+ transaction_without_slave_off(*args, &block)
51
+ end
52
+ end
53
+
54
+ module InstanceMethods
55
+ # fix ActiveRecord to do the right thing, and use our aliased quote_value
56
+ def quote_value(*args, &block)
57
+ self.class.quote_value(*args, &block)
58
+ end
59
+
60
+ def reload_with_slave_off(*args, &block)
61
+ self.class.on_master { reload_without_slave_off(*args, &block) }
62
+ end
63
+ end
64
+
65
+ CLASS_SLAVE_METHODS = [:find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :exists?].freeze
66
+
67
+ def self.extended(base)
68
+ CLASS_SLAVE_METHODS.each { |m| ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(true, base, m) }
69
+
70
+ base.class_eval do
71
+ include InstanceMethods
72
+
73
+ alias_method :reload_without_slave_off, :reload
74
+ alias_method :reload, :reload_with_slave_off
75
+
76
+ class << self
77
+ alias_method :columns_without_force_slave, :columns
78
+ alias_method :columns, :columns_with_force_slave
79
+
80
+ alias_method :table_exists_without_force_slave?, :table_exists?
81
+ alias_method :table_exists?, :table_exists_with_force_slave?
82
+
83
+ alias_method :transaction_without_slave_off, :transaction
84
+ alias_method :transaction, :transaction_with_slave_off
85
+ end
86
+ end
87
+ if ActiveRecord::Associations.const_defined?(:HasAndBelongsToManyAssociation)
88
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_sql)
89
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_find_options!)
90
+ end
91
+ end
92
+
93
+ def on_slave_unless_tx
94
+ if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
95
+ on_slave { yield }
96
+ else
97
+ yield
98
+ end
99
+ end
100
+
101
+ module ActiveRelationPatches
102
+ def self.included(base)
103
+ [:calculate, :exists?, :pluck, :find_with_associations].each do |m|
104
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, base, m)
105
+ end
106
+ end
107
+
108
+ def on_slave_unless_tx
109
+ @klass.on_slave_unless_tx { yield }
110
+ end
111
+ end
112
+
113
+ # in rails 4.1+, they create a join class that's used to pull in records for HABTM.
114
+ # this simplifies the hell out of our existence, because all we have to do is inerit on-slave-by-default
115
+ # down from the parent now.
116
+ module HasAndBelongsToManyBuilderExtension
117
+ def self.included(base)
118
+ base.class_eval do
119
+ alias_method :through_model_without_inherit_default_slave_from_lhs, :through_model
120
+ alias_method :through_model, :through_model_with_inherit_default_slave_from_lhs
121
+ end
122
+ end
123
+
124
+ def through_model_with_inherit_default_slave_from_lhs
125
+ model = through_model_without_inherit_default_slave_from_lhs
126
+ def model.on_slave_by_default?
127
+ left_reflection.klass.on_slave_by_default?
128
+ end
129
+
130
+ model.extend(ActiveRecordShards::Ext::ShardedModel) if model.left_reflection.klass.is_sharded?
131
+
132
+ model
133
+ end
134
+ end
135
+ end
5
136
  end
@@ -3,59 +3,44 @@
3
3
  module ActiveRecordShards
4
4
  module Model
5
5
  def not_sharded
6
- if self != ActiveRecord::Base && self != base_class
7
- raise "You should only call not_sharded on direct descendants of ActiveRecord::Base"
8
- end
9
-
10
- self.sharded = false
6
+ ActiveSupport::Deprecation.warn("Calling not_sharded is deprecated. "\
7
+ "Please ensure to still read from the "\
8
+ "account db slave after removing the "\
9
+ "call.")
11
10
  end
12
11
 
13
12
  def is_sharded? # rubocop:disable Naming/PredicateName
14
- if self == ActiveRecord::Base
15
- sharded != false && supports_sharding?
16
- elsif self == base_class
17
- if sharded.nil?
18
- ActiveRecord::Base.is_sharded?
19
- else
20
- sharded != false
21
- end
22
- else
23
- base_class.is_sharded?
24
- end
13
+ false
25
14
  end
26
15
 
27
- def on_replica_by_default?
16
+ def on_slave_by_default?
28
17
  if self == ActiveRecord::Base
29
18
  false
30
19
  else
31
20
  base = base_class
32
- if base.instance_variable_defined?(:@on_replica_by_default)
33
- base.instance_variable_get(:@on_replica_by_default)
21
+ if base.instance_variable_defined?(:@on_slave_by_default)
22
+ base.instance_variable_get(:@on_slave_by_default)
34
23
  end
35
24
  end
36
25
  end
37
- alias_method :on_slave_by_default?, :on_replica_by_default?
38
26
 
39
- def on_replica_by_default=(value)
27
+ def on_slave_by_default=(value)
40
28
  if self == ActiveRecord::Base
41
- raise ArgumentError, "Cannot set on_replica_by_default on ActiveRecord::Base"
29
+ raise ArgumentError, "Cannot set on_slave_by_default on ActiveRecord::Base"
42
30
  else
43
- base_class.instance_variable_set(:@on_replica_by_default, value)
31
+ base_class.instance_variable_set(:@on_slave_by_default, value)
44
32
  end
45
33
  end
46
- alias_method :on_slave_by_default=, :on_replica_by_default=
47
34
 
48
35
  module InstanceMethods
49
- def initialize_shard_and_replica
50
- @from_replica = !!self.class.current_shard_selection.options[:replica]
36
+ def initialize_shard_and_slave
37
+ @from_slave = !!self.class.current_shard_selection.options[:slave]
51
38
  @from_shard = self.class.current_shard_selection.options[:shard]
52
39
  end
53
- alias_method :initialize_shard_and_slave, :initialize_shard_and_replica
54
40
 
55
- def from_replica?
56
- @from_replica
41
+ def from_slave?
42
+ @from_slave
57
43
  end
58
- alias_method :from_slave?, :from_replica?
59
44
 
60
45
  def from_shard
61
46
  @from_shard
@@ -64,11 +49,7 @@ module ActiveRecordShards
64
49
 
65
50
  def self.extended(base)
66
51
  base.send(:include, InstanceMethods)
67
- base.after_initialize :initialize_shard_and_replica
52
+ base.after_initialize :initialize_shard_and_slave
68
53
  end
69
-
70
- private
71
-
72
- attr_accessor :sharded
73
54
  end
74
55
  end
@@ -1,91 +1,52 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module ActiveRecordShards
4
3
  class ShardSelection
5
- NO_SHARD = :_no_shard
6
- cattr_accessor :default_shard
7
-
8
- def initialize
9
- @on_replica = false
10
- @shard = nil
4
+ def initialize(shard)
5
+ @on_slave = false
6
+ self.shard = shard
11
7
  end
12
8
 
13
- if ActiveRecord::VERSION::MAJOR < 5
14
-
15
- def shard(klass = nil)
16
- if (@shard || self.class.default_shard) && (klass.nil? || klass.is_sharded?)
17
- if @shard == NO_SHARD
18
- nil
19
- else
20
- @shard || self.class.default_shard
21
- end
22
- end
23
- end
24
-
25
- def shard_name(klass = nil, try_replica = true)
26
- the_shard = shard(klass)
27
-
28
- @shard_names ||= {}
29
- @shard_names[ActiveRecordShards.app_env] ||= {}
30
- @shard_names[ActiveRecordShards.app_env][the_shard] ||= {}
31
- @shard_names[ActiveRecordShards.app_env][the_shard][try_replica] ||= {}
32
- @shard_names[ActiveRecordShards.app_env][the_shard][try_replica][@on_replica] ||= begin
33
- s = ActiveRecordShards.app_env.dup
34
- s << "_shard_#{the_shard}" if the_shard
35
- s << "_replica" if @on_replica && try_replica
36
- s
37
- end
38
- end
9
+ def shard
10
+ raise "Missing shard information on connection" unless @shard
11
+ @shard
12
+ end
39
13
 
40
- else
14
+ PRIMARY = "primary".freeze
15
+ def resolve_connection_name(sharded:, configurations:)
16
+ resolved_shard = sharded ? shard : nil
41
17
 
42
- def shard
43
- if @shard.nil? || @shard == NO_SHARD
44
- nil
45
- else
46
- @shard || self.class.default_shard
47
- end
18
+ if !resolved_shard && !@on_slave
19
+ return PRIMARY
48
20
  end
49
21
 
50
- PRIMARY = "primary"
51
- def resolve_connection_name(sharded:, configurations:)
52
- resolved_shard = sharded ? shard : nil
53
- env = ActiveRecordShards.app_env
22
+ @shard_names ||= {}
23
+ @shard_names[ActiveRecordShards.rails_env] ||= {}
24
+ @shard_names[ActiveRecordShards.rails_env][resolved_shard] ||= {}
25
+ @shard_names[ActiveRecordShards.rails_env][resolved_shard][@on_slave] ||= begin
26
+ s = ActiveRecordShards.rails_env.dup
27
+ s << "_shard_#{resolved_shard}" if resolved_shard
54
28
 
55
- @connection_names ||= {}
56
- @connection_names[env] ||= {}
57
- @connection_names[env][resolved_shard] ||= {}
58
- @connection_names[env][resolved_shard][@on_replica] ||= begin
59
- name = env.dup
60
- name << "_shard_#{resolved_shard}" if resolved_shard
61
- if @on_replica && configurations["#{name}_replica"]
62
- "#{name}_replica"
63
- else
64
- # ActiveRecord always names its default connection pool 'primary'
65
- # while everything else is named by the configuration name
66
- resolved_shard ? name : PRIMARY
67
- end
29
+ if @on_slave && configurations["#{s}_slave"] # fall back to master connection
30
+ s << "_slave"
68
31
  end
32
+ s
69
33
  end
70
-
71
34
  end
72
35
 
73
36
  def shard=(new_shard)
74
- @shard = (new_shard || NO_SHARD)
37
+ @shard = Integer(new_shard)
75
38
  end
76
39
 
77
- def on_replica?
78
- @on_replica
40
+ def on_slave?
41
+ @on_slave
79
42
  end
80
- alias_method :on_slave?, :on_replica?
81
43
 
82
- def on_replica=(new_replica)
83
- @on_replica = (new_replica == true)
44
+ def on_slave=(new_slave)
45
+ @on_slave = (new_slave == true)
84
46
  end
85
- alias_method :on_slave=, :on_replica=
86
47
 
87
48
  def options
88
- { shard: @shard, replica: @on_replica }
49
+ { shard: @shard, slave: @on_slave }
89
50
  end
90
51
  end
91
52
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module ActiveRecordShards
4
3
  class ShardSupport
5
4
  class ShardEnumerator
@@ -0,0 +1,15 @@
1
+ module ActiveRecordShards
2
+ module Ext
3
+ module ShardedModel
4
+ def is_sharded? # rubocop:disable Naming/PredicateName
5
+ true
6
+ end
7
+ end
8
+ end
9
+
10
+ class ShardedModel < ActiveRecord::Base
11
+ self.abstract_class = true
12
+
13
+ extend ActiveRecordShards::Ext::ShardedModel
14
+ end
15
+ end