active_record_shards 3.21.0 → 5.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aadf0c3e7681201dfc6b2f9ff1c9a33164d7e9b17394052e09601f807926c73a
4
- data.tar.gz: 3e1eaac98dbcdeb6133787447fdd4a7c56aa4056013e9b01aa2082f00a6bc733
3
+ metadata.gz: 032e2279ef2f82d2a1a30a171429a7b34b625766fe3a6060ad21141d551c0ca4
4
+ data.tar.gz: 169c3f8e0bf7d4f036a23106d8523b5e09756535f289be4da5ec295ec6c1605d
5
5
  SHA512:
6
- metadata.gz: eecd43504f6dcb074c97128d96a2b5bbeeea08bc92e6c005bc3b8d3952670ea7a201856709b50c0ad5e4d91db1eb9aac9bba02762a424eaa3a23bb44c00fbdbd
7
- data.tar.gz: 1f91bc255828d9bae15bf5267a5a836049e12eef663751dbad63de1f35e84cea566f071f290db96f84accc4bb20c2d52c82cbedbe79a6bc637769cae7aeafa75
6
+ metadata.gz: c35a082c7b33926009467f10871177ecb02a2c5dc3b009a1f5d1a889fb49f039ea88bb931cdd80c7cc67763120158748610925ece6d53ee463020388a4690cc5
7
+ data.tar.gz: 4acc42ae93f573d60d12384f6f7454b4a85d1a5a13239491cb6b00a10d722dfb1534026119f845b3f8c39c5e0114500099eac6806cc2c8b6864c7c9f74835fde
data/README.md CHANGED
@@ -5,7 +5,9 @@
5
5
  ActiveRecord Shards is an extension for ActiveRecord that provides support for sharded database and replicas. Basically it is just a nice way to
6
6
  switch between database connections. We've made the implementation very small, and have tried not to reinvent any wheels already present in ActiveRecord.
7
7
 
8
- ActiveRecord Shards has been used and tested on Rails 4.2, 5.x and 6.0, and has in some form or another been used in production on large Rails apps for several years.
8
+ ActiveRecord Shards has been used and tested on Rails 5.x and 6.0, and has in some form or another been used in production on large Rails apps for several years.
9
+
10
+ Rails 6.1 introduced new connection handling and support for sharding. Apps are encouraged to migrate to the native sharding logic but ActiveRecord Shards supports Rails 6.1 when `legacy_connection_handling` is set to `true`. For more information see [Rails 6.1 installation](#rails-61-installation) and Rails' [multiple databases guide](https://guides.rubyonrails.org/active_record_multiple_databases.html).
9
11
 
10
12
  - [Installation](#installation)
11
13
  - [Configuration](#configuration)
@@ -22,6 +24,22 @@ ActiveRecord Shards has been used and tested on Rails 4.2, 5.x and 6.0, and has
22
24
 
23
25
  and make sure to require 'active\_record\_shards' in some way.
24
26
 
27
+ ### Rails 6.1 & 7.0 installation
28
+
29
+ Rails 6.1 & 7.0 are **only** supported with `legacy_connection_handling` set to `true`.
30
+
31
+ Enable the legacy handling in your configuration files e.g. `config/application.rb` by setting:
32
+
33
+ ``` Ruby
34
+ config.active_record.legacy_connection_handling = true
35
+ ```
36
+
37
+ or
38
+
39
+ ``` Ruby
40
+ ActiveRecord::Base.legacy_connection_handling = true
41
+ ```
42
+
25
43
  ## Configuration
26
44
 
27
45
  Add the replica and shard configuration to config/database.yml:
@@ -5,32 +5,26 @@ module ActiveRecordShards
5
5
  def on_replica_if(condition)
6
6
  condition ? on_replica : self
7
7
  end
8
- alias_method :on_slave_if, :on_replica_if
9
8
 
10
9
  def on_replica_unless(condition)
11
10
  on_replica_if(!condition)
12
11
  end
13
- alias_method :on_slave_unless, :on_replica_unless
14
12
 
15
13
  def on_primary_if(condition)
16
14
  condition ? on_primary : self
17
15
  end
18
- alias_method :on_master_if, :on_primary_if
19
16
 
20
17
  def on_primary_unless(condition)
21
18
  on_primary_if(!condition)
22
19
  end
23
- alias_method :on_master_unless, :on_primary_unless
24
20
 
25
21
  def on_replica
26
22
  PrimaryReplicaProxy.new(self, :replica)
27
23
  end
28
- alias_method :on_slave, :on_replica
29
24
 
30
25
  def on_primary
31
26
  PrimaryReplicaProxy.new(self, :primary)
32
27
  end
33
- alias_method :on_master, :on_primary
34
28
 
35
29
  class PrimaryReplicaProxy
36
30
  def initialize(association_collection, which)
@@ -42,8 +36,7 @@ module ActiveRecordShards
42
36
  reflection = @association_collection.proxy_association.reflection
43
37
  reflection.klass.on_cx_switch_block(@which) { @association_collection.send(method, *args, &block) }
44
38
  end
39
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
45
40
  end
46
-
47
- MasterSlaveProxy = PrimaryReplicaProxy
48
41
  end
49
42
  end
@@ -28,27 +28,6 @@ module ActiveRecordShards
28
28
  expand_child!(env_config, replica_conf)
29
29
  conf["#{env_name}_replica"] = replica_conf
30
30
  end
31
-
32
- # rubocop:disable Style/Next
33
- if legacy_replica_conf = env_config.delete('slave')
34
- ActiveRecordShards::Deprecation.warn('`slave` configuration keys should be replaced with `replica` keys!')
35
- expand_child!(env_config, legacy_replica_conf)
36
- conf["#{env_name}_replica"] = legacy_replica_conf
37
- end
38
- # rubocop:enable Style/Next
39
- end
40
-
41
- conf
42
- end
43
-
44
- def replace_slave_keys(conf)
45
- conf.to_a.each do |env_name, env_config|
46
- next unless env_name.end_with?("_slave")
47
-
48
- replica_key = env_name.sub(/_slave$/, "_replica")
49
- next if conf.key?(replica_key)
50
-
51
- conf[replica_key] = env_config.deep_dup
52
31
  end
53
32
 
54
33
  conf
@@ -56,16 +35,14 @@ module ActiveRecordShards
56
35
 
57
36
  def expand_child!(parent, child)
58
37
  parent.each do |key, value|
59
- unless ['slave', 'replica', 'shards'].include?(key) || value.is_a?(Hash)
38
+ unless ['replica', 'shards'].include?(key) || value.is_a?(Hash)
60
39
  child[key] ||= value
61
40
  end
62
41
  end
63
42
  end
64
43
 
65
44
  def configurations_with_shard_explosion=(conf)
66
- exploded_configuration = explode(conf)
67
- configuration_with_slave_keys_replaced = replace_slave_keys(exploded_configuration)
68
- self.configurations_without_shard_explosion = configuration_with_slave_keys_replaced
45
+ self.configurations_without_shard_explosion = explode(conf)
69
46
  end
70
47
 
71
48
  def self.extended(base)
@@ -0,0 +1,31 @@
1
+ module ActiveRecordShards
2
+ module ConnectionSwitcher
3
+ def connection_specification_name
4
+ name = current_shard_selection.resolve_connection_name(sharded: is_sharded?, configurations: configurations)
5
+
6
+ @_ars_connection_specification_names ||= {}
7
+ unless @_ars_connection_specification_names.include?(name)
8
+ unless configurations.configs_for(env_name: name, include_replicas: true).any? || name == "ActiveRecord::Base"
9
+ raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.configurations.map(&:env_name).inspect})"
10
+ end
11
+
12
+ @_ars_connection_specification_names[name] = true
13
+ end
14
+
15
+ name
16
+ end
17
+
18
+ private
19
+
20
+ def ensure_shard_connection
21
+ # See if we've connected before. If not, call `#establish_connection`
22
+ # so that ActiveRecord can resolve connection_specification_name to an
23
+ # ARS connection.
24
+ spec_name = connection_specification_name
25
+
26
+ pool = connection_handler.retrieve_connection_pool(spec_name)
27
+
28
+ connection_handler.establish_connection(spec_name.to_sym) if pool.nil?
29
+ end
30
+ end
31
+ end
@@ -3,8 +3,13 @@ module ActiveRecordShards
3
3
  def connection_specification_name
4
4
  name = current_shard_selection.resolve_connection_name(sharded: is_sharded?, configurations: configurations)
5
5
 
6
- unless configurations[name] || name == "primary"
7
- raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.to_h.keys.inspect})"
6
+ @_ars_connection_specification_names ||= {}
7
+ unless @_ars_connection_specification_names.include?(name)
8
+ unless configurations.configs_for(env_name: name, include_hidden: true).any? || name == "ActiveRecord::Base"
9
+ raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.configurations.map(&:env_name).inspect})"
10
+ end
11
+
12
+ @_ars_connection_specification_names[name] = true
8
13
  end
9
14
 
10
15
  name
@@ -19,11 +24,8 @@ module ActiveRecordShards
19
24
  spec_name = connection_specification_name
20
25
 
21
26
  pool = connection_handler.retrieve_connection_pool(spec_name)
22
- if pool.nil?
23
- resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(configurations)
24
- spec = resolver.spec(spec_name.to_sym, spec_name)
25
- connection_handler.establish_connection(spec)
26
- end
27
+
28
+ connection_handler.establish_connection(spec_name.to_sym) if pool.nil?
27
29
  end
28
30
  end
29
31
  end
@@ -4,26 +4,23 @@ require 'active_record_shards/shard_support'
4
4
 
5
5
  module ActiveRecordShards
6
6
  module ConnectionSwitcher
7
- SHARD_NAMES_CONFIG_KEY = 'shard_names'
7
+ class LegacyConnectionHandlingError < StandardError; end
8
+
9
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
10
+ when '6.1', '7.0'
11
+ SHARD_NAMES_CONFIG_KEY = :shard_names
12
+ else
13
+ SHARD_NAMES_CONFIG_KEY = 'shard_names'
14
+ end
8
15
 
9
16
  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
17
+ base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!)
18
+ base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!)
17
19
 
18
20
  base.singleton_class.send(:alias_method, :table_exists_without_default_shard?, :table_exists?)
19
21
  base.singleton_class.send(:alias_method, :table_exists?, :table_exists_with_default_shard?)
20
22
  end
21
23
 
22
- def default_shard=(new_default_shard)
23
- ActiveRecordShards::ShardSelection.default_shard = new_default_shard
24
- switch_connection(shard: new_default_shard)
25
- end
26
-
27
24
  def on_primary_db(&block)
28
25
  on_shard(nil, &block)
29
26
  end
@@ -62,22 +59,18 @@ module ActiveRecordShards
62
59
  def on_replica_if(condition, &block)
63
60
  condition ? on_replica(&block) : yield
64
61
  end
65
- alias_method :on_slave_if, :on_replica_if
66
62
 
67
63
  def on_replica_unless(condition, &block)
68
64
  on_replica_if(!condition, &block)
69
65
  end
70
- alias_method :on_slave_unless, :on_replica_unless
71
66
 
72
67
  def on_primary_if(condition, &block)
73
68
  condition ? on_primary(&block) : yield
74
69
  end
75
- alias_method :on_master_if, :on_primary_if
76
70
 
77
71
  def on_primary_unless(condition, &block)
78
72
  on_primary_if(!condition, &block)
79
73
  end
80
- alias_method :on_master_unless, :on_primary_unless
81
74
 
82
75
  def on_primary_or_replica(which, &block)
83
76
  if block_given?
@@ -86,7 +79,6 @@ module ActiveRecordShards
86
79
  PrimaryReplicaProxy.new(self, which)
87
80
  end
88
81
  end
89
- alias_method :on_master_or_slave, :on_primary_or_replica
90
82
 
91
83
  # Executes queries using the replica database. Fails over to primary if no replica is found.
92
84
  # if you want to execute a block of code on the replica you can go:
@@ -100,25 +92,15 @@ module ActiveRecordShards
100
92
  def on_replica(&block)
101
93
  on_primary_or_replica(:replica, &block)
102
94
  end
103
- alias_method :on_slave, :on_replica
104
95
 
105
96
  def on_primary(&block)
106
97
  on_primary_or_replica(:primary, &block)
107
98
  end
108
- alias_method :on_master, :on_primary
109
-
110
- # just to ease the transition from replica to active_record_shards
111
- alias_method :with_slave, :on_replica
112
- alias_method :with_slave_if, :on_replica_if
113
- alias_method :with_slave_unless, :on_replica_unless
114
99
 
115
100
  def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block)
116
- @disallow_replica ||= 0
117
- @disallow_replica += 1 if [:primary, :master].include?(which)
118
-
119
- ActiveRecordShards::Deprecation.warn('the `:master` option should be replaced with `:primary`!') if which == :master
101
+ self.disallow_replica += 1 if which == :primary
120
102
 
121
- switch_to_replica = force || @disallow_replica.zero?
103
+ switch_to_replica = force || disallow_replica.zero?
122
104
  old_options = current_shard_selection.options
123
105
 
124
106
  switch_connection(replica: switch_to_replica)
@@ -131,10 +113,18 @@ module ActiveRecordShards
131
113
  readonly.scoping(&block)
132
114
  end
133
115
  ensure
134
- @disallow_replica -= 1 if [:primary, :master].include?(which)
116
+ self.disallow_replica -= 1 if which == :primary
135
117
  switch_connection(old_options) if old_options
136
118
  end
137
119
 
120
+ def disallow_replica=(value)
121
+ Thread.current[:__active_record_shards__disallow_replica_by_thread] = value
122
+ end
123
+
124
+ def disallow_replica
125
+ Thread.current[:__active_record_shards__disallow_replica_by_thread] ||= 0
126
+ end
127
+
138
128
  def supports_sharding?
139
129
  shard_names.any?
140
130
  end
@@ -142,7 +132,6 @@ module ActiveRecordShards
142
132
  def on_replica?
143
133
  current_shard_selection.on_replica?
144
134
  end
145
- alias_method :on_slave?, :on_replica?
146
135
 
147
136
  def current_shard_selection
148
137
  Thread.current[:shard_selection] ||= ShardSelection.new
@@ -165,7 +154,15 @@ module ActiveRecordShards
165
154
  def config_for_env
166
155
  @_ars_config_for_env ||= {}
167
156
  @_ars_config_for_env[shard_env] ||= begin
168
- unless config = configurations[shard_env]
157
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
158
+ when '7.0'
159
+ config = configurations.configs_for(env_name: shard_env, include_hidden: true).first.configuration_hash
160
+ when '6.1'
161
+ config = configurations.configs_for(env_name: shard_env, include_replicas: true).first.configuration_hash
162
+ else
163
+ config = configurations[shard_env]
164
+ end
165
+ unless config
169
166
  raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.to_h.keys.inspect})"
170
167
  end
171
168
 
@@ -175,6 +172,8 @@ module ActiveRecordShards
175
172
  alias_method :check_config_for_env, :config_for_env
176
173
 
177
174
  def switch_connection(options)
175
+ ensure_legacy_connection_handling if ActiveRecord.version >= Gem::Version.new('6.1')
176
+
178
177
  if options.any?
179
178
  if options.key?(:replica)
180
179
  current_shard_selection.on_replica = options[:replica]
@@ -190,6 +189,22 @@ module ActiveRecordShards
190
189
  end
191
190
  end
192
191
 
192
+ def ensure_legacy_connection_handling
193
+ unless legacy_connection_handling_owner.legacy_connection_handling
194
+ raise LegacyConnectionHandlingError, "ActiveRecordShards is _only_ compatible with ActiveRecord `legacy_connection_handling` set to `true`."
195
+ end
196
+ end
197
+
198
+ def legacy_connection_handling_owner
199
+ @legacy_connection_handling_owner ||=
200
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
201
+ when '7.0'
202
+ ActiveRecord
203
+ when '6.1'
204
+ ActiveRecord::Base
205
+ end
206
+ end
207
+
193
208
  def shard_env
194
209
  ActiveRecordShards.app_env
195
210
  end
@@ -204,14 +219,8 @@ module ActiveRecordShards
204
219
  end
205
220
  end
206
221
 
207
- if ActiveRecord::VERSION::MAJOR >= 5
208
- def load_schema_with_default_shard!
209
- with_default_shard { load_schema_without_default_shard! }
210
- end
211
- else
212
- def columns_with_default_shard
213
- with_default_shard { columns_without_default_shard }
214
- end
222
+ def load_schema_with_default_shard!
223
+ with_default_shard { load_schema_without_default_shard! }
215
224
  end
216
225
 
217
226
  def table_exists_with_default_shard?
@@ -227,21 +236,20 @@ module ActiveRecordShards
227
236
  def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
228
237
  @target.on_primary_or_replica(@which) { @target.send(method, *args, &block) }
229
238
  end
239
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
230
240
  end
231
-
232
- MasterSlaveProxy = PrimaryReplicaProxy
233
241
  end
234
242
  end
235
243
 
236
244
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
237
- when '4.2'
238
- require 'active_record_shards/connection_switcher-4-2'
239
- when '5.0'
240
- require 'active_record_shards/connection_switcher-5-0'
241
245
  when '5.1', '5.2'
242
246
  require 'active_record_shards/connection_switcher-5-1'
243
247
  when '6.0'
244
248
  require 'active_record_shards/connection_switcher-6-0'
249
+ when '6.1'
250
+ require 'active_record_shards/connection_switcher-6-1'
251
+ when '7.0'
252
+ require 'active_record_shards/connection_switcher-7-0'
245
253
  else
246
254
  raise "ActiveRecordShards is not compatible with #{ActiveRecord::VERSION::STRING}"
247
255
  end
@@ -22,21 +22,13 @@ module ActiveRecordShards
22
22
  #{method}_without_default_replica#{punctuation}(*args, &block)
23
23
  end
24
24
  end
25
-
25
+ ruby2_keywords(:#{method}_with_default_replica#{punctuation}) if respond_to?(:ruby2_keywords, true)
26
26
  alias_method :#{method}_without_default_replica#{punctuation}, :#{method}#{punctuation}
27
27
  alias_method :#{method}#{punctuation}, :#{method}_with_default_replica#{punctuation}
28
28
  #{class_method ? 'end' : ''}
29
29
  RUBY
30
30
  end
31
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
32
  def transaction_with_replica_off(*args, &block)
41
33
  if on_replica_by_default?
42
34
  begin
@@ -50,14 +42,9 @@ module ActiveRecordShards
50
42
  transaction_without_replica_off(*args, &block)
51
43
  end
52
44
  end
53
- alias_method :transaction_with_slave_off, :transaction_with_replica_off
45
+ ruby2_keywords(:transaction_with_replica_off) if respond_to?(:ruby2_keywords, true)
54
46
 
55
47
  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
48
  def on_replica_unless_tx
62
49
  self.class.on_replica_unless_tx { yield }
63
50
  end
@@ -84,19 +71,11 @@ module ActiveRecordShards
84
71
  :table_exists?
85
72
  ].freeze
86
73
 
87
- CLASS_SLAVE_METHODS = CLASS_REPLICA_METHODS
88
- CLASS_FORCE_SLAVE_METHODS = CLASS_FORCE_REPLICA_METHODS
89
-
90
74
  def self.extended(base)
91
75
  CLASS_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m) }
92
76
  CLASS_FORCE_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m, force_on_replica: true) }
93
77
 
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
-
78
+ ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, :load_schema!, force_on_replica: true)
100
79
  ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :reload)
101
80
 
102
81
  base.class_eval do
@@ -119,7 +98,6 @@ module ActiveRecordShards
119
98
  yield
120
99
  end
121
100
  end
122
- alias_method :on_slave_unless_tx, :on_replica_unless_tx
123
101
 
124
102
  def force_on_replica(&block)
125
103
  return yield if Thread.current[:_active_record_shards_in_migration]
@@ -133,11 +111,6 @@ module ActiveRecordShards
133
111
  ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, m)
134
112
  end
135
113
 
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
114
  ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :to_sql, force_on_replica: true)
142
115
  end
143
116
 
@@ -210,20 +183,6 @@ module ActiveRecordShards
210
183
  end
211
184
  end
212
185
 
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
186
  module AssociationsPreloaderAssociationAssociatedRecordsByOwnerPatch
228
187
  def associated_records_by_owner(preloader)
229
188
  if klass
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordShards
4
+ module DefaultShard
5
+ def default_shard=(new_default_shard)
6
+ if ars_shard_type?(new_default_shard)
7
+ ActiveRecordShards::ShardSelection.ars_default_shard = new_default_shard
8
+ switch_connection(shard: new_default_shard)
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def ars_shard_type?(shard)
17
+ return true if ActiveRecord.version < Gem::Version.new('6.1')
18
+ return true if shard.nil?
19
+ return true if shard == :_no_shard
20
+ return true if shard.is_a?(Integer)
21
+
22
+ false
23
+ end
24
+ end
25
+ end
26
+
27
+ ActiveRecord::Base.singleton_class.prepend(ActiveRecordShards::DefaultShard)
@@ -19,11 +19,10 @@ module ActiveRecord
19
19
  # manually on the sharded DBs.
20
20
  ActiveRecord::Base.on_all_shards do
21
21
  ActiveRecord::SchemaMigration.create_table
22
- if ActiveRecord::VERSION::MAJOR >= 5
23
- ActiveRecord::InternalMetadata.create_table
24
- end
22
+ ActiveRecord::InternalMetadata.create_table
25
23
  end
26
24
  end
25
+ ruby2_keywords(:initialize_with_sharding) if respond_to?(:ruby2_keywords, true)
27
26
  alias_method :initialize_without_sharding, :initialize
28
27
  alias_method :initialize, :initialize_with_sharding
29
28
 
@@ -34,7 +34,6 @@ module ActiveRecordShards
34
34
  end
35
35
  end
36
36
  end
37
- alias_method :on_slave_by_default?, :on_replica_by_default?
38
37
 
39
38
  def on_replica_by_default=(value)
40
39
  if self == ActiveRecord::Base
@@ -43,19 +42,16 @@ module ActiveRecordShards
43
42
  base_class.instance_variable_set(:@on_replica_by_default, value)
44
43
  end
45
44
  end
46
- alias_method :on_slave_by_default=, :on_replica_by_default=
47
45
 
48
46
  module InstanceMethods
49
47
  def initialize_shard_and_replica
50
48
  @from_replica = !!self.class.current_shard_selection.options[:replica]
51
49
  @from_shard = self.class.current_shard_selection.options[:shard]
52
50
  end
53
- alias_method :initialize_shard_and_slave, :initialize_shard_and_replica
54
51
 
55
52
  def from_replica?
56
53
  @from_replica
57
54
  end
58
- alias_method :from_slave?, :from_replica?
59
55
 
60
56
  def from_shard
61
57
  @from_shard
@@ -3,71 +3,54 @@
3
3
  module ActiveRecordShards
4
4
  class ShardSelection
5
5
  NO_SHARD = :_no_shard
6
- cattr_accessor :default_shard
6
+ cattr_accessor :ars_default_shard
7
7
 
8
8
  def initialize
9
9
  @on_replica = false
10
10
  @shard = nil
11
11
  end
12
12
 
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
13
+ def shard
14
+ if @shard.nil? || @shard == NO_SHARD
15
+ nil
16
+ else
17
+ @shard || self.class.ars_default_shard
38
18
  end
39
-
19
+ end
20
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
21
+ when '6.1', '7.0'
22
+ PRIMARY = "ActiveRecord::Base"
40
23
  else
41
-
42
- def shard
43
- if @shard.nil? || @shard == NO_SHARD
44
- nil
45
- else
46
- @shard || self.class.default_shard
47
- end
48
- end
49
-
50
24
  PRIMARY = "primary"
51
- def resolve_connection_name(sharded:, configurations:)
52
- resolved_shard = sharded ? shard : nil
53
- env = ActiveRecordShards.app_env
25
+ end
26
+ def resolve_connection_name(sharded:, configurations:)
27
+ resolved_shard = sharded ? shard : nil
28
+ env = ActiveRecordShards.app_env
54
29
 
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"
30
+ @connection_names ||= {}
31
+ @connection_names[env] ||= {}
32
+ @connection_names[env][resolved_shard] ||= {}
33
+ @connection_names[env][resolved_shard][@on_replica] ||= begin
34
+ name = env.dup
35
+ name << "_shard_#{resolved_shard}" if resolved_shard
36
+ replica_config = begin
37
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
38
+ when '7.0'
39
+ configurations.configs_for(env_name: "#{name}_replica", include_hidden: true).any?
40
+ when '6.1'
41
+ configurations.configs_for(env_name: "#{name}_replica", include_replicas: true).any?
63
42
  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
43
+ configurations["#{name}_replica"]
67
44
  end
68
45
  end
46
+ if @on_replica && replica_config
47
+ "#{name}_replica"
48
+ else
49
+ # ActiveRecord always names its default connection pool 'primary'
50
+ # while everything else is named by the configuration name
51
+ resolved_shard ? name : PRIMARY
52
+ end
69
53
  end
70
-
71
54
  end
72
55
 
73
56
  def shard=(new_shard)
@@ -77,12 +60,10 @@ module ActiveRecordShards
77
60
  def on_replica?
78
61
  @on_replica
79
62
  end
80
- alias_method :on_slave?, :on_replica?
81
63
 
82
64
  def on_replica=(new_replica)
83
65
  @on_replica = (new_replica == true)
84
66
  end
85
- alias_method :on_slave=, :on_replica=
86
67
 
87
68
  def options
88
69
  { shard: @shard, replica: @on_replica }
@@ -23,15 +23,14 @@ module ActiveRecordShards
23
23
 
24
24
  exception = nil
25
25
  enum.each do
26
- begin
27
- record = @scope.find(*find_args)
28
- return record if record
29
- rescue ActiveRecord::RecordNotFound => e
30
- exception = e
31
- end
26
+ record = @scope.find(*find_args)
27
+ return record if record
28
+ rescue ActiveRecord::RecordNotFound => e
29
+ exception = e
32
30
  end
33
31
  raise exception
34
32
  end
33
+ ruby2_keywords(:find) if respond_to?(:ruby2_keywords, true)
35
34
 
36
35
  def count
37
36
  enum.inject(0) { |accum, _shard| @scope.clone.count + accum }
@@ -9,10 +9,24 @@ end
9
9
  namespace :db do
10
10
  desc 'Drops the database for the current RAILS_ENV including shards'
11
11
  task drop: :load_config do
12
- ActiveRecord::Base.configurations.to_h.each do |key, conf|
13
- next if !key.start_with?(ActiveRecordShards.app_env) || key.end_with?("_replica", "_slave")
12
+ configurations = begin
13
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
14
+ when '6.1', '7.0'
15
+ ActiveRecord::Base.configurations.configurations.map { |configuration| [configuration.env_name, configuration.configuration_hash] }
16
+ else
17
+ ActiveRecord::Base.configurations.to_h
18
+ end
19
+ end
20
+
21
+ configurations.each do |key, conf|
22
+ next if !key.start_with?(ActiveRecordShards.app_env) || key.end_with?("_replica")
14
23
 
15
24
  begin
25
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
26
+ when '6.1', '7.0'
27
+ conf = conf.stringify_keys
28
+ end
29
+
16
30
  ActiveRecordShards::Tasks.root_connection(conf).drop_database(conf['database'])
17
31
  # rescue ActiveRecord::NoDatabaseError # TODO: exists in AR but never is raised here ...
18
32
  # $stderr.puts "Database '#{conf['database']}' does not exist"
@@ -30,13 +44,26 @@ namespace :db do
30
44
 
31
45
  desc "Create the database defined in config/database.yml for the current RAILS_ENV including shards"
32
46
  task create: :load_config do
33
- ActiveRecord::Base.configurations.to_h.each do |key, conf|
34
- next if !key.start_with?(ActiveRecordShards.app_env) || key.end_with?("_replica", "_slave")
47
+ configurations = begin
48
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
49
+ when '6.1', '7.0'
50
+ ActiveRecord::Base.configurations.configurations.map { |configuration| [configuration.env_name, configuration.configuration_hash] }
51
+ else
52
+ ActiveRecord::Base.configurations.to_h
53
+ end
54
+ end
55
+ configurations.each do |key, conf|
56
+ next if !key.start_with?(ActiveRecordShards.app_env) || key.end_with?("_replica")
35
57
 
36
58
  begin
37
59
  # MysqlAdapter takes charset instead of encoding in Rails 4.2 or greater
38
60
  # https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/tasks/mysql_database_tasks.rb#L85-L96
39
61
  symbolized_configuration = conf.symbolize_keys
62
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
63
+ when '6.1', '7.0'
64
+ conf = conf.stringify_keys
65
+ end
66
+
40
67
  symbolized_configuration[:charset] = symbolized_configuration[:encoding]
41
68
 
42
69
  ActiveRecordShards::Tasks.root_connection(conf).create_database(conf['database'], symbolized_configuration)
@@ -78,14 +105,12 @@ namespace :db do
78
105
  namespace :test do
79
106
  desc 'Purges the test databases by dropping and creating'
80
107
  task purge: :load_config do |t|
81
- begin
82
- saved_env = Rails.env
83
- Rails.env = 'test'
84
- Rake.application.lookup('db:drop', t.scope).execute
85
- Rake.application.lookup('db:create', t.scope).execute
86
- ensure
87
- Rails.env = saved_env
88
- end
108
+ saved_env = Rails.env
109
+ Rails.env = 'test'
110
+ Rake.application.lookup('db:drop', t.scope).execute
111
+ Rake.application.lookup('db:create', t.scope).execute
112
+ ensure
113
+ Rails.env = saved_env
89
114
  end
90
115
  end
91
116
  end
@@ -96,15 +121,26 @@ module ActiveRecordShards
96
121
  def root_connection(conf)
97
122
  conf = conf.merge('database' => nil)
98
123
  spec = spec_for(conf)
99
-
100
- ActiveRecord::Base.send("#{conf['adapter']}_connection", spec.config)
124
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
125
+ when '6.1', '7.0'
126
+ ActiveRecord::Base.send("#{conf['adapter']}_connection", spec.db_config.configuration_hash)
127
+ else
128
+ ActiveRecord::Base.send("#{conf['adapter']}_connection", spec.config)
129
+ end
101
130
  end
102
131
 
103
132
  private
104
133
 
105
134
  def spec_for(conf)
106
- resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(ActiveRecord::Base.configurations)
107
- resolver.spec(conf)
135
+ case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
136
+ when '7.0'
137
+ ActiveRecord::Base.connection_handler.send(:resolve_pool_config, conf, ActiveRecord::Base, ActiveRecord::Base.current_role, ActiveRecord::Base.current_shard)
138
+ when '6.1'
139
+ ActiveRecord::Base.connection_handler.send(:resolve_pool_config, conf, ActiveRecord::Base)
140
+ else
141
+ resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(ActiveRecord::Base.configurations)
142
+ resolver.spec(conf)
143
+ end
108
144
  end
109
145
  end
110
146
  end
@@ -9,6 +9,7 @@ require 'active_record_shards/connection_switcher'
9
9
  require 'active_record_shards/association_collection_connection_selection'
10
10
  require 'active_record_shards/migration'
11
11
  require 'active_record_shards/default_replica_patches'
12
+ require 'active_record_shards/default_shard'
12
13
  require 'active_record_shards/schema_dumper_extension'
13
14
 
14
15
  module ActiveRecordShards
@@ -36,32 +37,6 @@ ActiveRecord::Associations::Builder::HasAndBelongsToMany.include(ActiveRecordSha
36
37
  ActiveRecord::SchemaDumper.prepend(ActiveRecordShards::SchemaDumperExtension)
37
38
 
38
39
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
39
- when '4.2'
40
- require 'active_record_shards/patches-4-2'
41
-
42
- # https://github.com/rails/rails/blob/v4.2.11.3/activerecord/lib/active_record/associations/association.rb#L97
43
- ActiveRecord::Associations::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationAssociationScopePatch)
44
-
45
- # https://github.com/rails/rails/blob/v4.2.11.3/activerecord/lib/active_record/associations/singular_association.rb#L44-L53
46
- ActiveRecord::Associations::SingularAssociation.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationGetRecordsPatch)
47
-
48
- # https://github.com/rails/rails/blob/v4.2.11.3/activerecord/lib/active_record/associations/collection_association.rb#L447-L456
49
- ActiveRecord::Associations::CollectionAssociation.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationGetRecordsPatch)
50
-
51
- # https://github.com/rails/rails/blob/v4.2.11.3/activerecord/lib/active_record/associations/preloader/association.rb#L89
52
- ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsPreloaderAssociationAssociatedRecordsByOwnerPatch)
53
- when '5.0'
54
- # https://github.com/rails/rails/blob/v5.0.7/activerecord/lib/active_record/associations/association.rb#L97
55
- ActiveRecord::Associations::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationAssociationScopePatch)
56
-
57
- # https://github.com/rails/rails/blob/v5.0.7/activerecord/lib/active_record/associations/singular_association.rb#L56-L65
58
- ActiveRecord::Associations::SingularAssociation.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationGetRecordsPatch)
59
-
60
- # https://github.com/rails/rails/blob/v5.0.7/activerecord/lib/active_record/associations/collection_association.rb#L442-L451
61
- ActiveRecord::Associations::CollectionAssociation.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationGetRecordsPatch)
62
-
63
- # https://github.com/rails/rails/blob/v5.0.7/activerecord/lib/active_record/associations/preloader/association.rb#L120
64
- ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsPreloaderAssociationLoadRecordsPatch)
65
40
  when '5.1'
66
41
  # https://github.com/rails/rails/blob/v5.1.7/activerecord/lib/active_record/associations/association.rb#L97
67
42
  ActiveRecord::Associations::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsAssociationAssociationScopePatch)
@@ -87,7 +62,7 @@ when '5.2'
87
62
 
88
63
  # https://github.com/rails/rails/blob/v5.2.6/activerecord/lib/active_record/associations/preloader/association.rb#L96
89
64
  ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecordShards::DefaultReplicaPatches::AssociationsPreloaderAssociationLoadRecordsPatch)
90
- when '6.0'
65
+ when '6.0', '6.1', '7.0'
91
66
  # https://github.com/rails/rails/blob/v6.0.4/activerecord/lib/active_record/type_caster/connection.rb#L28
92
67
  ActiveRecord::TypeCaster::Connection.prepend(ActiveRecordShards::DefaultReplicaPatches::TypeCasterConnectionConnectionPatch)
93
68
 
@@ -103,45 +78,3 @@ when '6.0'
103
78
  else
104
79
  raise "ActiveRecordShards is not compatible with #{ActiveRecord::VERSION::STRING}"
105
80
  end
106
-
107
- require 'active_record_shards/deprecation'
108
-
109
- ActiveRecordShards::Deprecation.deprecate_methods(
110
- ActiveRecordShards::AssociationCollectionConnectionSelection,
111
- on_slave_if: :on_replica_if,
112
- on_slave_unless: :on_replica_unless,
113
- on_slave: :on_replica,
114
- on_master: :on_primary,
115
- on_master_if: :on_primary_if,
116
- on_master_unless: :on_primary_unless
117
- )
118
-
119
- ActiveRecordShards::Deprecation.deprecate_methods(
120
- ActiveRecordShards::ConnectionSwitcher,
121
- on_slave_if: :on_replica_if,
122
- on_slave_unless: :on_replica_unless,
123
- on_master_or_slave: :on_primary_or_replica,
124
- on_slave: :on_replica,
125
- on_master: :on_primary,
126
- on_master_if: :on_primary_if,
127
- on_master_unless: :on_primary_unless,
128
- on_slave?: :on_replica?
129
- )
130
-
131
- ActiveRecordShards::Deprecation.deprecate_methods(
132
- ActiveRecordShards::DefaultReplicaPatches,
133
- transaction_with_slave_off: :transaction_with_replica_off,
134
- on_slave_unless_tx: :on_replica_unless_tx
135
- )
136
-
137
- ActiveRecordShards::Deprecation.deprecate_methods(
138
- ActiveRecordShards::Model,
139
- on_slave_by_default?: :on_replica_by_default?,
140
- :on_slave_by_default= => :on_replica_by_default=
141
- )
142
-
143
- ActiveRecordShards::Deprecation.deprecate_methods(
144
- ActiveRecordShards::ShardSelection,
145
- on_slave?: :on_replica?,
146
- :on_slave= => :on_replica=
147
- )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_shards
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.21.0
4
+ version: 5.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Quorning
@@ -10,10 +10,10 @@ authors:
10
10
  - Mick Staugaard
11
11
  - Eric Chapweske
12
12
  - Ben Osheroff
13
- autorequire:
13
+ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2022-07-05 00:00:00.000000000 Z
16
+ date: 2023-02-14 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: activerecord
@@ -21,40 +21,40 @@ dependencies:
21
21
  requirements:
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: '4.2'
24
+ version: '5.1'
25
25
  - - "<"
26
26
  - !ruby/object:Gem::Version
27
- version: '6.1'
27
+ version: '7.1'
28
28
  type: :runtime
29
29
  prerelease: false
30
30
  version_requirements: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '4.2'
34
+ version: '5.1'
35
35
  - - "<"
36
36
  - !ruby/object:Gem::Version
37
- version: '6.1'
37
+ version: '7.1'
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: activesupport
40
40
  requirement: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: '4.2'
44
+ version: '5.1'
45
45
  - - "<"
46
46
  - !ruby/object:Gem::Version
47
- version: '6.1'
47
+ version: '7.1'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '4.2'
54
+ version: '5.1'
55
55
  - - "<"
56
56
  - !ruby/object:Gem::Version
57
- version: '6.1'
57
+ version: '7.1'
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: bump
60
60
  requirement: !ruby/object:Gem::Requirement
@@ -97,20 +97,6 @@ dependencies:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
- - !ruby/object:Gem::Dependency
101
- name: mocha
102
- requirement: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- version: 1.4.0
107
- type: :development
108
- prerelease: false
109
- version_requirements: !ruby/object:Gem::Requirement
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- version: 1.4.0
114
100
  - !ruby/object:Gem::Dependency
115
101
  name: mysql2
116
102
  requirement: !ruby/object:Gem::Requirement
@@ -195,20 +181,15 @@ files:
195
181
  - lib/active_record_shards.rb
196
182
  - lib/active_record_shards/association_collection_connection_selection.rb
197
183
  - lib/active_record_shards/configuration_parser.rb
198
- - lib/active_record_shards/connection_handler.rb
199
- - lib/active_record_shards/connection_pool.rb
200
- - lib/active_record_shards/connection_specification.rb
201
- - lib/active_record_shards/connection_switcher-4-2.rb
202
- - lib/active_record_shards/connection_switcher-5-0.rb
203
184
  - lib/active_record_shards/connection_switcher-5-1.rb
204
185
  - lib/active_record_shards/connection_switcher-6-0.rb
186
+ - lib/active_record_shards/connection_switcher-6-1.rb
187
+ - lib/active_record_shards/connection_switcher-7-0.rb
205
188
  - lib/active_record_shards/connection_switcher.rb
206
189
  - lib/active_record_shards/default_replica_patches.rb
207
- - lib/active_record_shards/default_slave_patches.rb
208
- - lib/active_record_shards/deprecation.rb
190
+ - lib/active_record_shards/default_shard.rb
209
191
  - lib/active_record_shards/migration.rb
210
192
  - lib/active_record_shards/model.rb
211
- - lib/active_record_shards/patches-4-2.rb
212
193
  - lib/active_record_shards/schema_dumper_extension.rb
213
194
  - lib/active_record_shards/shard_selection.rb
214
195
  - lib/active_record_shards/shard_support.rb
@@ -218,7 +199,7 @@ homepage: https://github.com/zendesk/active_record_shards
218
199
  licenses:
219
200
  - MIT
220
201
  metadata: {}
221
- post_install_message:
202
+ post_install_message:
222
203
  rdoc_options: []
223
204
  require_paths:
224
205
  - lib
@@ -226,15 +207,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
226
207
  requirements:
227
208
  - - ">="
228
209
  - !ruby/object:Gem::Version
229
- version: '2.3'
210
+ version: '2.6'
230
211
  required_rubygems_version: !ruby/object:Gem::Requirement
231
212
  requirements:
232
213
  - - ">="
233
214
  - !ruby/object:Gem::Version
234
215
  version: '0'
235
216
  requirements: []
236
- rubygems_version: 3.1.6
237
- signing_key:
217
+ rubygems_version: 3.0.3.1
218
+ signing_key:
238
219
  specification_version: 4
239
220
  summary: Simple database switching for ActiveRecord.
240
221
  test_files: []
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ActiveRecord::ConnectionAdapters::ConnectionHandler.class_eval do
4
- remove_method :retrieve_connection_pool
5
- def retrieve_connection_pool(klass)
6
- class_to_pool[klass.connection_pool_name] ||= pool_for(klass)
7
- end
8
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordShards
4
- ConnectionPoolNameDecorator = Struct.new(:name)
5
-
6
- # It overrides given connection handler methods (they differ depend on
7
- # Rails version).
8
- #
9
- # It takes the first argument, ActiveRecord::Base object or
10
- # String (connection_pool_name), converts it in Struct object and
11
- # passes to the original method.
12
- #
13
- # Example:
14
- # methods_to_override = [:establish_connection, :remove_connection]
15
- # ActiveRecordShards.override_connection_handler_methods(methods_to_override)
16
- #
17
- def self.override_connection_handler_methods(method_names)
18
- method_names.each do |method_name|
19
- ActiveRecord::ConnectionAdapters::ConnectionHandler.class_eval do
20
- define_method("#{method_name}_with_connection_pool_name") do |*args|
21
- unless args[0].is_a? ConnectionPoolNameDecorator
22
- name = if args[0].is_a? String
23
- args[0]
24
- else
25
- args[0].connection_pool_name
26
- end
27
- args[0] = ConnectionPoolNameDecorator.new(name)
28
- end
29
- send("#{method_name}_without_connection_pool_name", *args)
30
- end
31
- alias_method :"#{method_name}_without_connection_pool_name", method_name
32
- alias_method method_name, :"#{method_name}_with_connection_pool_name"
33
- end
34
- end
35
- end
36
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class << ActiveRecord::Base
4
- remove_method :establish_connection if ActiveRecord::VERSION::MAJOR >= 5
5
- def establish_connection(spec = ENV["DATABASE_URL"])
6
- spec ||= ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
7
- spec = spec.to_sym if spec.is_a?(String)
8
- resolver = ActiveRecordShards::ConnectionSpecification::Resolver.new configurations
9
- spec = resolver.spec(spec)
10
-
11
- unless respond_to?(spec.adapter_method)
12
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
13
- end
14
-
15
- remove_connection
16
- specification_cache[connection_pool_name] = spec
17
- connection_handler.establish_connection self, spec
18
- end
19
- end
@@ -1,56 +0,0 @@
1
- module ActiveRecordShards
2
- module ConnectionSwitcher
3
- # Name of the connection pool. Used by ConnectionHandler to retrieve the current connection pool.
4
- def connection_pool_name # :nodoc:
5
- name = current_shard_selection.shard_name(self)
6
-
7
- # e.g. if "production_replica" is not defined in `Configuration`, fall back to "production"
8
- if configurations[name].nil? && on_replica?
9
- current_shard_selection.shard_name(self, false)
10
- else
11
- name
12
- end
13
- end
14
-
15
- private
16
-
17
- def ensure_shard_connection
18
- establish_shard_connection unless connected_to_shard?
19
- end
20
-
21
- def establish_shard_connection
22
- name = connection_pool_name
23
- spec = configurations[name]
24
-
25
- if spec.nil?
26
- raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.keys.inspect})"
27
- end
28
-
29
- specification_cache[name] ||= begin
30
- resolver = ActiveRecordShards::ConnectionSpecification::Resolver.new configurations
31
- resolver.spec(spec)
32
- end
33
-
34
- connection_handler.establish_connection(self, specification_cache[name])
35
- end
36
-
37
- def specification_cache
38
- @@specification_cache ||= {}
39
- end
40
-
41
- # Helper method to clear global state when testing.
42
- def clear_specification_cache
43
- @@specification_cache = {}
44
- end
45
-
46
- def connection_pool_key
47
- specification_cache[connection_pool_name]
48
- end
49
-
50
- def connected_to_shard?
51
- specs_to_pools = Hash[connection_handler.connection_pool_list.map { |pool| [pool.spec, pool] }]
52
-
53
- specs_to_pools.key?(connection_pool_key)
54
- end
55
- end
56
- end
@@ -1,5 +0,0 @@
1
- ActiveRecordShards::Deprecation.warn('`DefaultSlavePatches` is deprecated, please use `DefaultReplicaPatches`.')
2
-
3
- module ActiveRecordShards
4
- DefaultSlavePatches = DefaultReplicaPatches
5
- end
@@ -1,12 +0,0 @@
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,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record_shards/connection_pool'
4
- require 'active_record_shards/connection_handler'
5
- require 'active_record_shards/connection_specification'
6
-
7
- ActiveRecordShards::ConnectionSpecification = ActiveRecord::ConnectionAdapters::ConnectionSpecification
8
- methods_to_override = [:establish_connection, :remove_connection, :pool_for, :pool_from_any_process_for]
9
- ActiveRecordShards.override_connection_handler_methods(methods_to_override)