active_record_shards 3.11.0 → 3.19.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 +5 -5
- data/README.md +120 -57
- data/lib/active_record_shards/association_collection_connection_selection.rb +23 -16
- data/lib/active_record_shards/configuration_parser.rb +19 -5
- data/lib/active_record_shards/connection_handler.rb +3 -8
- data/lib/active_record_shards/connection_pool.rb +1 -0
- data/lib/active_record_shards/connection_specification.rb +7 -16
- data/lib/active_record_shards/connection_switcher-4-2.rb +56 -0
- data/lib/active_record_shards/connection_switcher-5-0.rb +1 -1
- data/lib/active_record_shards/connection_switcher-5-1.rb +1 -1
- data/lib/active_record_shards/connection_switcher.rb +89 -61
- data/lib/active_record_shards/default_replica_patches.rb +278 -0
- data/lib/active_record_shards/default_slave_patches.rb +3 -148
- data/lib/active_record_shards/deprecation.rb +12 -0
- data/lib/active_record_shards/migration.rb +35 -31
- data/lib/active_record_shards/model.rb +26 -10
- data/lib/active_record_shards/patches-4-2.rb +1 -5
- data/lib/active_record_shards/schema_dumper_extension.rb +6 -5
- data/lib/active_record_shards/shard_selection.rb +28 -26
- data/lib/active_record_shards/shard_support.rb +1 -0
- data/lib/active_record_shards/sql_comments.rb +11 -4
- data/lib/active_record_shards/tasks.rb +40 -35
- data/lib/active_record_shards.rb +111 -7
- metadata +61 -58
- data/lib/active_record_shards/connection_switcher-4-0.rb +0 -68
- data/lib/active_record_shards/patches-3-2.rb +0 -11
- data/lib/active_record_shards/patches-5-0.rb +0 -13
@@ -1,13 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'active_record_shards/shard_support'
|
3
4
|
|
4
5
|
module ActiveRecordShards
|
5
6
|
module ConnectionSwitcher
|
6
|
-
SHARD_NAMES_CONFIG_KEY = 'shard_names'
|
7
|
+
SHARD_NAMES_CONFIG_KEY = 'shard_names'
|
7
8
|
|
8
9
|
def self.extended(base)
|
9
|
-
|
10
|
-
|
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
|
11
17
|
|
12
18
|
base.singleton_class.send(:alias_method, :table_exists_without_default_shard?, :table_exists?)
|
13
19
|
base.singleton_class.send(:alias_method, :table_exists?, :table_exists_with_default_shard?)
|
@@ -18,6 +24,10 @@ module ActiveRecordShards
|
|
18
24
|
switch_connection(shard: new_default_shard)
|
19
25
|
end
|
20
26
|
|
27
|
+
def on_primary_db(&block)
|
28
|
+
on_shard(nil, &block)
|
29
|
+
end
|
30
|
+
|
21
31
|
def on_shard(shard)
|
22
32
|
old_options = current_shard_selection.options
|
23
33
|
switch_connection(shard: shard) if supports_sharding?
|
@@ -26,9 +36,9 @@ module ActiveRecordShards
|
|
26
36
|
switch_connection(old_options)
|
27
37
|
end
|
28
38
|
|
29
|
-
def on_first_shard
|
39
|
+
def on_first_shard(&block)
|
30
40
|
shard_name = shard_names.first
|
31
|
-
on_shard(shard_name)
|
41
|
+
on_shard(shard_name, &block)
|
32
42
|
end
|
33
43
|
|
34
44
|
def shards
|
@@ -49,70 +59,79 @@ module ActiveRecordShards
|
|
49
59
|
switch_connection(old_options)
|
50
60
|
end
|
51
61
|
|
52
|
-
def
|
53
|
-
condition ?
|
62
|
+
def on_replica_if(condition, &block)
|
63
|
+
condition ? on_replica(&block) : yield
|
54
64
|
end
|
65
|
+
alias_method :on_slave_if, :on_replica_if
|
55
66
|
|
56
|
-
def
|
57
|
-
|
67
|
+
def on_replica_unless(condition, &block)
|
68
|
+
on_replica_if(!condition, &block)
|
58
69
|
end
|
70
|
+
alias_method :on_slave_unless, :on_replica_unless
|
59
71
|
|
60
|
-
def
|
61
|
-
condition ?
|
72
|
+
def on_primary_if(condition, &block)
|
73
|
+
condition ? on_primary(&block) : yield
|
62
74
|
end
|
75
|
+
alias_method :on_master_if, :on_primary_if
|
63
76
|
|
64
|
-
def
|
65
|
-
|
77
|
+
def on_primary_unless(condition, &block)
|
78
|
+
on_primary_if(!condition, &block)
|
66
79
|
end
|
80
|
+
alias_method :on_master_unless, :on_primary_unless
|
67
81
|
|
68
|
-
def
|
82
|
+
def on_primary_or_replica(which, &block)
|
69
83
|
if block_given?
|
70
84
|
on_cx_switch_block(which, &block)
|
71
85
|
else
|
72
|
-
|
86
|
+
PrimaryReplicaProxy.new(self, which)
|
73
87
|
end
|
74
88
|
end
|
89
|
+
alias_method :on_master_or_slave, :on_primary_or_replica
|
75
90
|
|
76
|
-
# Executes queries using the
|
77
|
-
# if you want to execute a block of code on the
|
78
|
-
# Account.
|
91
|
+
# Executes queries using the replica database. Fails over to primary if no replica is found.
|
92
|
+
# if you want to execute a block of code on the replica you can go:
|
93
|
+
# Account.on_replica do
|
79
94
|
# Account.first
|
80
95
|
# end
|
81
|
-
# the first account will be found on the
|
96
|
+
# the first account will be found on the replica DB
|
82
97
|
#
|
83
98
|
# For one-liners you can simply do
|
84
|
-
# Account.
|
85
|
-
def
|
86
|
-
|
99
|
+
# Account.on_replica.first
|
100
|
+
def on_replica(&block)
|
101
|
+
on_primary_or_replica(:replica, &block)
|
87
102
|
end
|
103
|
+
alias_method :on_slave, :on_replica
|
88
104
|
|
89
|
-
def
|
90
|
-
|
105
|
+
def on_primary(&block)
|
106
|
+
on_primary_or_replica(:primary, &block)
|
91
107
|
end
|
108
|
+
alias_method :on_master, :on_primary
|
92
109
|
|
93
110
|
# just to ease the transition from replica to active_record_shards
|
94
|
-
alias_method :with_slave, :
|
95
|
-
alias_method :with_slave_if, :
|
96
|
-
alias_method :with_slave_unless, :
|
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
|
97
114
|
|
98
115
|
def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block)
|
99
|
-
@
|
100
|
-
@
|
116
|
+
@disallow_replica ||= 0
|
117
|
+
@disallow_replica += 1 if [:primary, :master].include?(which)
|
101
118
|
|
102
|
-
|
119
|
+
ActiveRecordShards::Deprecation.warn('the `:master` option should be replaced with `:primary`!') if which == :master
|
120
|
+
|
121
|
+
switch_to_replica = force || @disallow_replica.zero?
|
103
122
|
old_options = current_shard_selection.options
|
104
123
|
|
105
|
-
switch_connection(
|
124
|
+
switch_connection(replica: switch_to_replica)
|
106
125
|
|
107
126
|
# we avoid_readonly_scope to prevent some stack overflow problems, like when
|
108
127
|
# .columns calls .with_scope which calls .columns and onward, endlessly.
|
109
|
-
if self == ActiveRecord::Base || !
|
128
|
+
if self == ActiveRecord::Base || !switch_to_replica || construct_ro_scope == false
|
110
129
|
yield
|
111
130
|
else
|
112
131
|
readonly.scoping(&block)
|
113
132
|
end
|
114
133
|
ensure
|
115
|
-
@
|
134
|
+
@disallow_replica -= 1 if [:primary, :master].include?(which)
|
116
135
|
switch_connection(old_options) if old_options
|
117
136
|
end
|
118
137
|
|
@@ -120,9 +139,10 @@ module ActiveRecordShards
|
|
120
139
|
shard_names.any?
|
121
140
|
end
|
122
141
|
|
123
|
-
def
|
124
|
-
current_shard_selection.
|
142
|
+
def on_replica?
|
143
|
+
current_shard_selection.on_replica?
|
125
144
|
end
|
145
|
+
alias_method :on_slave?, :on_replica?
|
126
146
|
|
127
147
|
def current_shard_selection
|
128
148
|
Thread.current[:shard_selection] ||= ShardSelection.new
|
@@ -134,8 +154,12 @@ module ActiveRecordShards
|
|
134
154
|
|
135
155
|
def shard_names
|
136
156
|
unless config = configurations[shard_env]
|
137
|
-
raise "Did not find #{shard_env} in configurations, did you forget to add it to your database
|
157
|
+
raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.keys.inspect})"
|
158
|
+
end
|
159
|
+
unless config.fetch(SHARD_NAMES_CONFIG_KEY, []).all? { |shard_name| shard_name.is_a?(Integer) }
|
160
|
+
raise "All shard names must be integers: #{config[SHARD_NAMES_CONFIG_KEY].inspect}."
|
138
161
|
end
|
162
|
+
|
139
163
|
config[SHARD_NAMES_CONFIG_KEY] || []
|
140
164
|
end
|
141
165
|
|
@@ -143,11 +167,15 @@ module ActiveRecordShards
|
|
143
167
|
|
144
168
|
def switch_connection(options)
|
145
169
|
if options.any?
|
146
|
-
if options.key?(:
|
147
|
-
current_shard_selection.
|
170
|
+
if options.key?(:replica)
|
171
|
+
current_shard_selection.on_replica = options[:replica]
|
148
172
|
end
|
149
173
|
|
150
174
|
if options.key?(:shard)
|
175
|
+
unless configurations[shard_env]
|
176
|
+
raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.keys.inspect})"
|
177
|
+
end
|
178
|
+
|
151
179
|
current_shard_selection.shard = options[:shard]
|
152
180
|
end
|
153
181
|
|
@@ -159,51 +187,51 @@ module ActiveRecordShards
|
|
159
187
|
ActiveRecordShards.rails_env
|
160
188
|
end
|
161
189
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
end
|
170
|
-
else
|
171
|
-
def with_default_shard
|
172
|
-
if is_sharded? && current_shard_id.nil? && table_name != ActiveRecord::Migrator.schema_migrations_table_name
|
173
|
-
on_first_shard { yield }
|
174
|
-
else
|
175
|
-
yield
|
176
|
-
end
|
190
|
+
# Make these few schema related methods available before having switched to
|
191
|
+
# a shard.
|
192
|
+
def with_default_shard(&block)
|
193
|
+
if is_sharded? && current_shard_id.nil? && table_name != ActiveRecord::SchemaMigration.table_name
|
194
|
+
on_first_shard(&block)
|
195
|
+
else
|
196
|
+
yield
|
177
197
|
end
|
178
198
|
end
|
179
199
|
|
180
|
-
|
181
|
-
|
200
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
201
|
+
def load_schema_with_default_shard!
|
202
|
+
with_default_shard { load_schema_without_default_shard! }
|
203
|
+
end
|
204
|
+
else
|
205
|
+
def columns_with_default_shard
|
206
|
+
with_default_shard { columns_without_default_shard }
|
207
|
+
end
|
182
208
|
end
|
183
209
|
|
184
210
|
def table_exists_with_default_shard?
|
185
211
|
with_default_shard { table_exists_without_default_shard? }
|
186
212
|
end
|
187
213
|
|
188
|
-
class
|
214
|
+
class PrimaryReplicaProxy
|
189
215
|
def initialize(target, which)
|
190
216
|
@target = target
|
191
217
|
@which = which
|
192
218
|
end
|
193
219
|
|
194
|
-
def method_missing(method, *args, &block) # rubocop:disable Style/
|
195
|
-
@target.
|
220
|
+
def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
|
221
|
+
@target.on_primary_or_replica(@which) { @target.send(method, *args, &block) }
|
196
222
|
end
|
197
223
|
end
|
224
|
+
|
225
|
+
MasterSlaveProxy = PrimaryReplicaProxy
|
198
226
|
end
|
199
227
|
end
|
200
228
|
|
201
229
|
case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
|
202
|
-
when '
|
203
|
-
require 'active_record_shards/connection_switcher-4-
|
230
|
+
when '4.2'
|
231
|
+
require 'active_record_shards/connection_switcher-4-2'
|
204
232
|
when '5.0'
|
205
233
|
require 'active_record_shards/connection_switcher-5-0'
|
206
|
-
when '5.1'
|
234
|
+
when '5.1', '5.2', '6.0'
|
207
235
|
require 'active_record_shards/connection_switcher-5-1'
|
208
236
|
else
|
209
237
|
raise "ActiveRecordShards is not compatible with #{ActiveRecord::VERSION::STRING}"
|
@@ -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
|