active_record_shards 5.3.2 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d54a5e8446f89d23e9c302763e48033f2398a72495d150772ea4bc3ec4fe575
4
- data.tar.gz: 9add02d3fec821e54c6f388a021cb09f69320de09846242e49fa2f26269ce948
3
+ metadata.gz: fbcc8e394ddfa2267939c38fe1612c0c410f549ca6d45fc52469ccd564771fcd
4
+ data.tar.gz: 2e87a9063cfe63fe47d58d5bf8e7b84dc88755cb39f81b88db3954a8c5a65868
5
5
  SHA512:
6
- metadata.gz: 27627d24f879c675af2d414c334fd713f9845f2e7d93dd8e6c580194357bba038f5c1ded593be06702a570e7631beeb92e5c2be8e26d8629b5ef84b3333e4b47
7
- data.tar.gz: d47b1b6906e5ff40633ebe6128fdc845cac7b81d377a16fd31ece96398a174fe87f8bd2a33406abe3516f53969ab5c910e163a792fb0f93e2e6119c8dfc15267
6
+ metadata.gz: 5eec3bce25a92f77f583a258efd2f054efce9f58b4e49c72be84e3cf352da02d7a8ab984ba349014dbe0f28b45cf347d2935512e97c88c349a9507b6338ce9f1
7
+ data.tar.gz: 4d9778bd1883639073fe77cf36a5de42de5d14ac1acd45303e80f4c37998a3c5ec00445578df9367a298c8d2c07111b2dd41e7cd6545b4e3f05f3b95d1eb2386
@@ -5,6 +5,7 @@ require 'active_record_shards/shard_support'
5
5
  module ActiveRecordShards
6
6
  module ConnectionSwitcher
7
7
  class LegacyConnectionHandlingError < StandardError; end
8
+ class IsolationLevelError < StandardError; end
8
9
 
9
10
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
10
11
  when '6.1', '7.0'
@@ -134,7 +135,8 @@ module ActiveRecordShards
134
135
  end
135
136
 
136
137
  def current_shard_selection
137
- Thread.current[:shard_selection] ||= ShardSelection.new
138
+ cs = Thread.current.thread_variable_get(:shard_selection) || ShardSelection.new
139
+ Thread.current.thread_variable_set(:shard_selection, cs)
138
140
  end
139
141
 
140
142
  def current_shard_id
@@ -177,6 +179,7 @@ module ActiveRecordShards
177
179
 
178
180
  def switch_connection(options)
179
181
  ensure_legacy_connection_handling if ActiveRecord.version >= Gem::Version.new('6.1')
182
+ ensure_thread_isolation_level if ActiveRecord.version >= Gem::Version.new('7.0')
180
183
 
181
184
  if options.any?
182
185
  if options.key?(:replica)
@@ -199,6 +202,12 @@ module ActiveRecordShards
199
202
  end
200
203
  end
201
204
 
205
+ def ensure_thread_isolation_level
206
+ unless ActiveSupport::IsolatedExecutionState.isolation_level == :thread
207
+ raise IsolationLevelError, "ActiveRecordShards is _only_ compatible when ActiveSupport::IsolatedExecutionState's isolation_level is set to :thread"
208
+ end
209
+ end
210
+
202
211
  def legacy_connection_handling_owner
203
212
  @legacy_connection_handling_owner ||=
204
213
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
@@ -29,21 +29,6 @@ module ActiveRecordShards
29
29
  RUBY
30
30
  end
31
31
 
32
- def transaction_with_replica_off(*args, &block)
33
- if on_replica_by_default?
34
- begin
35
- old_val = Thread.current[:_active_record_shards_in_tx]
36
- Thread.current[:_active_record_shards_in_tx] = true
37
- transaction_without_replica_off(*args, &block)
38
- ensure
39
- Thread.current[:_active_record_shards_in_tx] = old_val
40
- end
41
- else
42
- transaction_without_replica_off(*args, &block)
43
- end
44
- end
45
- ruby2_keywords(:transaction_with_replica_off) if respond_to?(:ruby2_keywords, true)
46
-
47
32
  module InstanceMethods
48
33
  def on_replica_unless_tx
49
34
  self.class.on_replica_unless_tx { yield }
@@ -80,17 +65,12 @@ module ActiveRecordShards
80
65
 
81
66
  base.class_eval do
82
67
  include InstanceMethods
83
-
84
- class << self
85
- alias_method :transaction_without_replica_off, :transaction
86
- alias_method :transaction, :transaction_with_replica_off
87
- end
88
68
  end
89
69
  end
90
70
 
91
71
  def on_replica_unless_tx(&block)
92
72
  return yield if Thread.current[:_active_record_shards_in_migration]
93
- return yield if Thread.current[:_active_record_shards_in_tx]
73
+ return yield if _in_transaction?
94
74
 
95
75
  if on_replica_by_default?
96
76
  on_replica(&block)
@@ -99,6 +79,10 @@ module ActiveRecordShards
99
79
  end
100
80
  end
101
81
 
82
+ def _in_transaction?
83
+ connected? && connection.transaction_open?
84
+ end
85
+
102
86
  def force_on_replica(&block)
103
87
  return yield if Thread.current[:_active_record_shards_in_migration]
104
88
 
@@ -122,7 +106,7 @@ module ActiveRecordShards
122
106
  module Rails52RelationPatches
123
107
  def connection
124
108
  return super if Thread.current[:_active_record_shards_in_migration]
125
- return super if Thread.current[:_active_record_shards_in_tx]
109
+ return super if _in_transaction?
126
110
 
127
111
  if @klass.on_replica_by_default?
128
112
  @klass.on_replica.connection
@@ -214,7 +198,7 @@ module ActiveRecordShards
214
198
  module TypeCasterConnectionConnectionPatch
215
199
  def connection
216
200
  return super if Thread.current[:_active_record_shards_in_migration]
217
- return super if Thread.current[:_active_record_shards_in_tx]
201
+ return super if ActiveRecord::Base._in_transaction?
218
202
 
219
203
  if @klass.on_replica_by_default?
220
204
  @klass.on_replica.connection
@@ -11,26 +11,20 @@ module ActiveRecordShards
11
11
  end
12
12
 
13
13
  def is_sharded? # rubocop:disable Naming/PredicateName
14
- # "sharded" here means self.sharded, but actually writing "self.sharded"
15
- # doesn't work until Ruby 2.7 (and this gem currently supports 2.6) because
16
- # the sharded attr_accessor is private. Private methods must be called without
17
- # a receiver, but Ruby 2.7+ does allow an explicit "self" as a receiver.
18
- return sharded unless sharded.nil?
14
+ return @_ars_model_is_sharded unless @_ars_model_is_sharded.nil?
19
15
 
20
- # Despite self.sharded not working, self.sharded= _DOES_ work. That's an exception
21
- # to the "private methods must be called with no receiver" rule (presumably
22
- # because it would otherwise be ambiguous with local variable assignment).
23
- self.sharded = if self == ActiveRecord::Base
24
- sharded != false && supports_sharding?
25
- elsif self == base_class
26
- if sharded.nil?
27
- ActiveRecord::Base.is_sharded?
28
- else
29
- sharded != false
30
- end
31
- else
32
- base_class.is_sharded?
33
- end
16
+ @_ars_model_is_sharded =
17
+ if self == ActiveRecord::Base
18
+ sharded != false && supports_sharding?
19
+ elsif self == base_class
20
+ if sharded.nil?
21
+ ActiveRecord::Base.is_sharded?
22
+ else
23
+ sharded != false
24
+ end
25
+ else
26
+ base_class.is_sharded?
27
+ end
34
28
  end
35
29
 
36
30
  def on_replica_by_default?
@@ -27,6 +27,17 @@ module ActiveRecordShards
27
27
  env || 'development'
28
28
  end
29
29
  end
30
+
31
+ # Busts internal caches kept by active_record_shards, for things which are _supposed_ to be the
32
+ # same for the life of the process. You shouldn't need to call this unless you're doing something
33
+ # truly evil like changing RAILS_ENV after boot
34
+ def self.reset_app_env!
35
+ @app_env = nil
36
+ models = [ActiveRecord::Base] + ActiveRecord::Base.descendants
37
+ models.each do |model|
38
+ model.remove_instance_variable(:@_ars_model_is_sharded) if model.instance_variable_defined?(:@_ars_model_is_sharded)
39
+ end
40
+ end
30
41
  end
31
42
 
32
43
  ActiveRecord::Base.extend(ActiveRecordShards::ConfigurationParser)
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: 5.3.2
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Quorning
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2023-04-06 00:00:00.000000000 Z
16
+ date: 2023-08-03 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: activerecord
@@ -83,20 +83,6 @@ dependencies:
83
83
  - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: 5.10.0
86
- - !ruby/object:Gem::Dependency
87
- name: minitest-rg
88
- requirement: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- version: '0'
93
- type: :development
94
- prerelease: false
95
- version_requirements: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- version: '0'
100
86
  - !ruby/object:Gem::Dependency
101
87
  name: mysql2
102
88
  requirement: !ruby/object:Gem::Requirement