active_record_shards 3.22.0 → 4.0.0.beta1
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 +57 -126
- data/lib/active_record_shards/association_collection_connection_selection.rb +14 -23
- data/lib/active_record_shards/configuration_parser.rb +6 -30
- data/lib/active_record_shards/connection_switcher-5-0.rb +0 -10
- data/lib/active_record_shards/connection_switcher-5-1.rb +0 -10
- data/lib/active_record_shards/connection_switcher.rb +71 -115
- data/lib/active_record_shards/default_slave_patches.rb +134 -3
- data/lib/active_record_shards/model.rb +16 -35
- data/lib/active_record_shards/shard_selection.rb +27 -66
- data/lib/active_record_shards/shard_support.rb +0 -1
- data/lib/active_record_shards/sharded_model.rb +15 -0
- data/lib/active_record_shards/sql_comments.rb +4 -11
- data/lib/active_record_shards/tasks.rb +22 -41
- data/lib/active_record_shards.rb +6 -126
- metadata +64 -74
- data/lib/active_record_shards/connection_handler.rb +0 -8
- data/lib/active_record_shards/connection_pool.rb +0 -36
- data/lib/active_record_shards/connection_specification.rb +0 -19
- data/lib/active_record_shards/connection_switcher-4-2.rb +0 -56
- data/lib/active_record_shards/connection_switcher-6-0.rb +0 -30
- data/lib/active_record_shards/default_replica_patches.rb +0 -278
- data/lib/active_record_shards/deprecation.rb +0 -12
- data/lib/active_record_shards/migration.rb +0 -125
- data/lib/active_record_shards/patches-4-2.rb +0 -9
- data/lib/active_record_shards/schema_dumper_extension.rb +0 -42
@@ -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,30 +0,0 @@
|
|
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[name] || name == "primary"
|
9
|
-
raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.to_h.keys.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
|
-
connection_handler.establish_connection(spec_name.to_sym) if pool.nil?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,278 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecordShards
|
4
|
-
module DefaultReplicaPatches
|
5
|
-
def self.wrap_method_in_on_replica(class_method, base, method, force_on_replica: false)
|
6
|
-
base_methods =
|
7
|
-
if class_method
|
8
|
-
base.methods + base.private_methods
|
9
|
-
else
|
10
|
-
base.instance_methods + base.private_instance_methods
|
11
|
-
end
|
12
|
-
|
13
|
-
return unless base_methods.include?(method)
|
14
|
-
|
15
|
-
_, method, punctuation = method.to_s.match(/^(.*?)([\?\!]?)$/).to_a
|
16
|
-
# _ALWAYS_ on replica, or only for on `on_replica_by_default = true` models?
|
17
|
-
wrapper = force_on_replica ? 'force_on_replica' : 'on_replica_unless_tx'
|
18
|
-
base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
19
|
-
#{class_method ? 'class << self' : ''}
|
20
|
-
def #{method}_with_default_replica#{punctuation}(*args, &block)
|
21
|
-
#{wrapper} do
|
22
|
-
#{method}_without_default_replica#{punctuation}(*args, &block)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
alias_method :#{method}_without_default_replica#{punctuation}, :#{method}#{punctuation}
|
27
|
-
alias_method :#{method}#{punctuation}, :#{method}_with_default_replica#{punctuation}
|
28
|
-
#{class_method ? 'end' : ''}
|
29
|
-
RUBY
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.wrap_method_in_on_slave(*args)
|
33
|
-
ActiveRecordShards::Deprecation.deprecation_warning(
|
34
|
-
:'self.wrap_method_in_on_slave',
|
35
|
-
:'self.wrap_method_in_on_replica'
|
36
|
-
)
|
37
|
-
wrap_method_in_on_replica(*args)
|
38
|
-
end
|
39
|
-
|
40
|
-
def transaction_with_replica_off(*args, &block)
|
41
|
-
if on_replica_by_default?
|
42
|
-
begin
|
43
|
-
old_val = Thread.current[:_active_record_shards_in_tx]
|
44
|
-
Thread.current[:_active_record_shards_in_tx] = true
|
45
|
-
transaction_without_replica_off(*args, &block)
|
46
|
-
ensure
|
47
|
-
Thread.current[:_active_record_shards_in_tx] = old_val
|
48
|
-
end
|
49
|
-
else
|
50
|
-
transaction_without_replica_off(*args, &block)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
alias_method :transaction_with_slave_off, :transaction_with_replica_off
|
54
|
-
|
55
|
-
module InstanceMethods
|
56
|
-
# fix ActiveRecord to do the right thing, and use our aliased quote_value
|
57
|
-
def quote_value(*args, &block)
|
58
|
-
self.class.quote_value(*args, &block)
|
59
|
-
end
|
60
|
-
|
61
|
-
def on_replica_unless_tx
|
62
|
-
self.class.on_replica_unless_tx { yield }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
CLASS_REPLICA_METHODS = [
|
67
|
-
:calculate,
|
68
|
-
:count_by_sql,
|
69
|
-
:exists?,
|
70
|
-
:find,
|
71
|
-
:find_by,
|
72
|
-
:find_by_sql,
|
73
|
-
:find_every,
|
74
|
-
:find_one,
|
75
|
-
:find_some,
|
76
|
-
:get_primary_key
|
77
|
-
].freeze
|
78
|
-
|
79
|
-
CLASS_FORCE_REPLICA_METHODS = [
|
80
|
-
:replace_bind_variable,
|
81
|
-
:replace_bind_variables,
|
82
|
-
:sanitize_sql_array,
|
83
|
-
:sanitize_sql_hash_for_assignment,
|
84
|
-
:table_exists?
|
85
|
-
].freeze
|
86
|
-
|
87
|
-
CLASS_SLAVE_METHODS = CLASS_REPLICA_METHODS
|
88
|
-
CLASS_FORCE_SLAVE_METHODS = CLASS_FORCE_REPLICA_METHODS
|
89
|
-
|
90
|
-
def self.extended(base)
|
91
|
-
CLASS_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m) }
|
92
|
-
CLASS_FORCE_REPLICA_METHODS.each { |m| ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, m, force_on_replica: true) }
|
93
|
-
|
94
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
95
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, :load_schema!, force_on_replica: true)
|
96
|
-
else
|
97
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(true, base, :columns, force_on_replica: true)
|
98
|
-
end
|
99
|
-
|
100
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :reload)
|
101
|
-
|
102
|
-
base.class_eval do
|
103
|
-
include InstanceMethods
|
104
|
-
|
105
|
-
class << self
|
106
|
-
alias_method :transaction_without_replica_off, :transaction
|
107
|
-
alias_method :transaction, :transaction_with_replica_off
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def on_replica_unless_tx(&block)
|
113
|
-
return yield if Thread.current[:_active_record_shards_in_migration]
|
114
|
-
return yield if Thread.current[:_active_record_shards_in_tx]
|
115
|
-
|
116
|
-
if on_replica_by_default?
|
117
|
-
on_replica(&block)
|
118
|
-
else
|
119
|
-
yield
|
120
|
-
end
|
121
|
-
end
|
122
|
-
alias_method :on_slave_unless_tx, :on_replica_unless_tx
|
123
|
-
|
124
|
-
def force_on_replica(&block)
|
125
|
-
return yield if Thread.current[:_active_record_shards_in_migration]
|
126
|
-
|
127
|
-
on_cx_switch_block(:replica, construct_ro_scope: false, force: true, &block)
|
128
|
-
end
|
129
|
-
|
130
|
-
module ActiveRelationPatches
|
131
|
-
def self.included(base)
|
132
|
-
[:calculate, :exists?, :pluck, :load].each do |m|
|
133
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, m)
|
134
|
-
end
|
135
|
-
|
136
|
-
if ActiveRecord::VERSION::MAJOR == 4
|
137
|
-
# `where` and `having` clauses call `create_binds`, which will use the primary connection
|
138
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :create_binds, force_on_replica: true)
|
139
|
-
end
|
140
|
-
|
141
|
-
ActiveRecordShards::DefaultReplicaPatches.wrap_method_in_on_replica(false, base, :to_sql, force_on_replica: true)
|
142
|
-
end
|
143
|
-
|
144
|
-
def on_replica_unless_tx
|
145
|
-
@klass.on_replica_unless_tx { yield }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
module Rails52RelationPatches
|
150
|
-
def connection
|
151
|
-
return super if Thread.current[:_active_record_shards_in_migration]
|
152
|
-
return super if Thread.current[:_active_record_shards_in_tx]
|
153
|
-
|
154
|
-
if @klass.on_replica_by_default?
|
155
|
-
@klass.on_replica.connection
|
156
|
-
else
|
157
|
-
super
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# in rails 4.1+, they create a join class that's used to pull in records for HABTM.
|
163
|
-
# this simplifies the hell out of our existence, because all we have to do is inerit on-replica-by-default
|
164
|
-
# down from the parent now.
|
165
|
-
module Rails41HasAndBelongsToManyBuilderExtension
|
166
|
-
def self.included(base)
|
167
|
-
base.class_eval do
|
168
|
-
alias_method :through_model_without_inherit_default_replica_from_lhs, :through_model
|
169
|
-
alias_method :through_model, :through_model_with_inherit_default_replica_from_lhs
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def through_model_with_inherit_default_replica_from_lhs
|
174
|
-
model = through_model_without_inherit_default_replica_from_lhs
|
175
|
-
def model.on_replica_by_default?
|
176
|
-
left_reflection.klass.on_replica_by_default?
|
177
|
-
end
|
178
|
-
|
179
|
-
# also transfer the sharded-ness of the left table to the join model
|
180
|
-
model.not_sharded unless model.left_reflection.klass.is_sharded?
|
181
|
-
model
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
module AssociationsAssociationAssociationScopePatch
|
186
|
-
def association_scope
|
187
|
-
if klass
|
188
|
-
on_replica_unless_tx { super }
|
189
|
-
else
|
190
|
-
super
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def on_replica_unless_tx
|
195
|
-
klass.on_replica_unless_tx { yield }
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
module AssociationsAssociationFindTargetPatch
|
200
|
-
def find_target
|
201
|
-
if klass
|
202
|
-
on_replica_unless_tx { super }
|
203
|
-
else
|
204
|
-
super
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def on_replica_unless_tx
|
209
|
-
klass.on_replica_unless_tx { yield }
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
module AssociationsAssociationGetRecordsPatch
|
214
|
-
def get_records # rubocop:disable Naming/AccessorMethodName
|
215
|
-
if klass
|
216
|
-
on_replica_unless_tx { super }
|
217
|
-
else
|
218
|
-
super
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def on_replica_unless_tx
|
223
|
-
klass.on_replica_unless_tx { yield }
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
module AssociationsPreloaderAssociationAssociatedRecordsByOwnerPatch
|
228
|
-
def associated_records_by_owner(preloader)
|
229
|
-
if klass
|
230
|
-
on_replica_unless_tx { super }
|
231
|
-
else
|
232
|
-
super
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def on_replica_unless_tx
|
237
|
-
klass.on_replica_unless_tx { yield }
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
module AssociationsPreloaderAssociationLoadRecordsPatch
|
242
|
-
def load_records
|
243
|
-
if klass
|
244
|
-
on_replica_unless_tx { super }
|
245
|
-
else
|
246
|
-
super
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
def on_replica_unless_tx
|
251
|
-
klass.on_replica_unless_tx { yield }
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
module TypeCasterConnectionConnectionPatch
|
256
|
-
def connection
|
257
|
-
return super if Thread.current[:_active_record_shards_in_migration]
|
258
|
-
return super if Thread.current[:_active_record_shards_in_tx]
|
259
|
-
|
260
|
-
if @klass.on_replica_by_default?
|
261
|
-
@klass.on_replica.connection
|
262
|
-
else
|
263
|
-
super
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
module SchemaDefinePatch
|
269
|
-
def define(info, &block)
|
270
|
-
old_val = Thread.current[:_active_record_shards_in_migration]
|
271
|
-
Thread.current[:_active_record_shards_in_migration] = true
|
272
|
-
super
|
273
|
-
ensure
|
274
|
-
Thread.current[:_active_record_shards_in_migration] = old_val
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
@@ -1,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,125 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecord
|
4
|
-
class Migrator
|
5
|
-
def self.shards_migration_context
|
6
|
-
if ActiveRecord::VERSION::MAJOR >= 6
|
7
|
-
ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::SchemaMigration)
|
8
|
-
elsif ActiveRecord::VERSION::STRING >= '5.2.0'
|
9
|
-
ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)
|
10
|
-
else
|
11
|
-
self
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize_with_sharding(*args)
|
16
|
-
initialize_without_sharding(*args)
|
17
|
-
|
18
|
-
# Rails creates the internal tables on the unsharded DB. We make them
|
19
|
-
# manually on the sharded DBs.
|
20
|
-
ActiveRecord::Base.on_all_shards do
|
21
|
-
ActiveRecord::SchemaMigration.create_table
|
22
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
23
|
-
ActiveRecord::InternalMetadata.create_table
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
alias_method :initialize_without_sharding, :initialize
|
28
|
-
alias_method :initialize, :initialize_with_sharding
|
29
|
-
|
30
|
-
def run_with_sharding
|
31
|
-
ActiveRecord::Base.on_shard(nil) { run_without_sharding }
|
32
|
-
ActiveRecord::Base.on_all_shards { run_without_sharding }
|
33
|
-
end
|
34
|
-
alias_method :run_without_sharding, :run
|
35
|
-
alias_method :run, :run_with_sharding
|
36
|
-
|
37
|
-
def migrate_with_sharding
|
38
|
-
ActiveRecord::Base.on_shard(nil) { migrate_without_sharding }
|
39
|
-
ActiveRecord::Base.on_all_shards { migrate_without_sharding }
|
40
|
-
end
|
41
|
-
alias_method :migrate_without_sharding, :migrate
|
42
|
-
alias_method :migrate, :migrate_with_sharding
|
43
|
-
|
44
|
-
# don't allow Migrator class to cache versions
|
45
|
-
undef migrated
|
46
|
-
def migrated
|
47
|
-
self.class.shards_migration_context.get_all_versions
|
48
|
-
end
|
49
|
-
|
50
|
-
# list of pending migrations is any migrations that haven't run on all shards.
|
51
|
-
undef pending_migrations
|
52
|
-
def pending_migrations
|
53
|
-
pending, _missing = self.class.shard_status(migrations.map(&:version))
|
54
|
-
pending = pending.values.flatten
|
55
|
-
migrations.select { |m| pending.include?(m.version) }
|
56
|
-
end
|
57
|
-
|
58
|
-
# public
|
59
|
-
# list of pending and missing versions per shard
|
60
|
-
# [{1 => [1234567]}, {1 => [2345678]}]
|
61
|
-
def self.shard_status(versions)
|
62
|
-
pending = {}
|
63
|
-
missing = {}
|
64
|
-
|
65
|
-
collect = lambda do |shard|
|
66
|
-
migrated = shards_migration_context.get_all_versions
|
67
|
-
|
68
|
-
p = versions - migrated
|
69
|
-
pending[shard] = p if p.any?
|
70
|
-
|
71
|
-
m = migrated - versions
|
72
|
-
missing[shard] = m if m.any?
|
73
|
-
end
|
74
|
-
|
75
|
-
ActiveRecord::Base.on_shard(nil) { collect.call(nil) }
|
76
|
-
ActiveRecord::Base.on_all_shards { |shard| collect.call(shard) }
|
77
|
-
|
78
|
-
[pending, missing]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
module ActiveRecordShards
|
84
|
-
module MigrationClassExtension
|
85
|
-
attr_accessor :migration_shard
|
86
|
-
|
87
|
-
def shard(arg = nil)
|
88
|
-
self.migration_shard = arg
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
module ActualMigrationExtension
|
93
|
-
def migrate_with_forced_shard(direction)
|
94
|
-
if migration_shard.blank?
|
95
|
-
raise "#{name}: Can't run migrations without a shard spec: this may be :all, :none,
|
96
|
-
or a specific shard (for data-fixups). please call shard(arg) in your migration."
|
97
|
-
end
|
98
|
-
|
99
|
-
shard = ActiveRecord::Base.current_shard_selection.shard
|
100
|
-
|
101
|
-
if shard.nil?
|
102
|
-
return if migration_shard != :none
|
103
|
-
else
|
104
|
-
return if migration_shard == :none
|
105
|
-
return if migration_shard != :all && migration_shard.to_s != shard.to_s
|
106
|
-
end
|
107
|
-
|
108
|
-
migrate_without_forced_shard(direction)
|
109
|
-
end
|
110
|
-
|
111
|
-
def migration_shard
|
112
|
-
self.class.migration_shard
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
ActiveRecord::Migration.class_eval do
|
118
|
-
extend ActiveRecordShards::MigrationClassExtension
|
119
|
-
include ActiveRecordShards::ActualMigrationExtension
|
120
|
-
|
121
|
-
alias_method :migrate_without_forced_shard, :migrate
|
122
|
-
alias_method :migrate, :migrate_with_forced_shard
|
123
|
-
end
|
124
|
-
|
125
|
-
ActiveRecord::MigrationProxy.delegate :migration_shard, to: :migration
|
@@ -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)
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecordShards
|
4
|
-
module SchemaDumperExtension
|
5
|
-
def dump(stream)
|
6
|
-
stream = super(stream)
|
7
|
-
original_connection = @connection
|
8
|
-
|
9
|
-
if ActiveRecord::Base.supports_sharding?
|
10
|
-
ActiveRecord::Base.on_first_shard do
|
11
|
-
@connection = ActiveRecord::Base.connection
|
12
|
-
shard_header(stream)
|
13
|
-
extensions(stream)
|
14
|
-
tables(stream)
|
15
|
-
shard_trailer(stream)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
stream
|
20
|
-
ensure
|
21
|
-
@connection = original_connection
|
22
|
-
end
|
23
|
-
|
24
|
-
def shard_header(stream)
|
25
|
-
define_params = @version ? "version: #{@version}" : ""
|
26
|
-
|
27
|
-
stream.puts <<~HEADER
|
28
|
-
|
29
|
-
|
30
|
-
# This section generated by active_record_shards
|
31
|
-
|
32
|
-
ActiveRecord::Base.on_all_shards do
|
33
|
-
ActiveRecord::Schema.define(#{define_params}) do
|
34
|
-
|
35
|
-
HEADER
|
36
|
-
end
|
37
|
-
|
38
|
-
def shard_trailer(stream)
|
39
|
-
stream.puts "end\nend"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|