switchman 3.0.2 → 3.1.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 +4 -4
- data/Rakefile +1 -1
- data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
- data/db/migrate/20180828192111_add_timestamps_to_shards.rb +1 -1
- data/lib/switchman/action_controller/caching.rb +2 -2
- data/lib/switchman/active_record/abstract_adapter.rb +2 -13
- data/lib/switchman/active_record/associations.rb +223 -0
- data/lib/switchman/active_record/attribute_methods.rb +144 -63
- data/lib/switchman/active_record/base.rb +100 -43
- data/lib/switchman/active_record/calculations.rb +12 -5
- data/lib/switchman/active_record/connection_pool.rb +9 -31
- data/lib/switchman/active_record/database_configurations.rb +18 -2
- data/lib/switchman/active_record/finder_methods.rb +2 -2
- data/lib/switchman/active_record/migration.rb +7 -4
- data/lib/switchman/active_record/model_schema.rb +1 -1
- data/lib/switchman/active_record/persistence.rb +7 -2
- data/lib/switchman/active_record/postgresql_adapter.rb +6 -2
- data/lib/switchman/active_record/predicate_builder.rb +1 -1
- data/lib/switchman/active_record/query_methods.rb +27 -14
- data/lib/switchman/active_record/reflection.rb +1 -1
- data/lib/switchman/active_record/relation.rb +25 -24
- data/lib/switchman/active_record/statement_cache.rb +2 -2
- data/lib/switchman/active_record/table_definition.rb +1 -1
- data/lib/switchman/active_record/test_fixtures.rb +43 -0
- data/lib/switchman/active_support/cache.rb +16 -0
- data/lib/switchman/arel.rb +28 -6
- data/lib/switchman/database_server.rb +71 -65
- data/lib/switchman/default_shard.rb +0 -2
- data/lib/switchman/engine.rb +67 -125
- data/lib/switchman/errors.rb +4 -2
- data/lib/switchman/guard_rail/relation.rb +6 -9
- data/lib/switchman/guard_rail.rb +5 -0
- data/lib/switchman/parallel.rb +68 -0
- data/lib/switchman/r_spec_helper.rb +5 -17
- data/lib/switchman/rails.rb +1 -4
- data/{app/models → lib}/switchman/shard.rb +61 -188
- data/lib/switchman/sharded_instrumenter.rb +1 -1
- data/lib/switchman/standard_error.rb +11 -12
- data/{app/models → lib}/switchman/unsharded_record.rb +1 -1
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +22 -2
- data/lib/tasks/switchman.rake +24 -13
- metadata +24 -22
- data/lib/switchman/active_record/association.rb +0 -206
- data/lib/switchman/open4.rb +0 -80
|
@@ -9,13 +9,13 @@ module Switchman
|
|
|
9
9
|
|
|
10
10
|
def initialize(*, **)
|
|
11
11
|
super
|
|
12
|
-
self.shard_value = Shard.current(klass ? klass.
|
|
12
|
+
self.shard_value = Shard.current(klass ? klass.connection_class_for_self : :primary) unless shard_value
|
|
13
13
|
self.shard_source_value = :implicit unless shard_source_value
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def clone
|
|
17
17
|
result = super
|
|
18
|
-
result.shard_value = Shard.current(klass ? klass.
|
|
18
|
+
result.shard_value = Shard.current(klass ? klass.connection_class_for_self : :primary) unless shard_value
|
|
19
19
|
result
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -29,41 +29,38 @@ module Switchman
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def new(*, &block)
|
|
32
|
-
primary_shard.activate(klass.
|
|
32
|
+
primary_shard.activate(klass.connection_class_for_self) { super }
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def create(*, &block)
|
|
36
|
-
primary_shard.activate(klass.
|
|
36
|
+
primary_shard.activate(klass.connection_class_for_self) { super }
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def create!(*, &block)
|
|
40
|
-
primary_shard.activate(klass.
|
|
40
|
+
primary_shard.activate(klass.connection_class_for_self) { super }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def to_sql
|
|
44
|
-
primary_shard.activate(klass.
|
|
44
|
+
primary_shard.activate(klass.connection_class_for_self) { super }
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def explain
|
|
48
48
|
activate { |relation| relation.call_super(:explain, Relation) }
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
results = activate { |relation| relation.call_super(:records, Relation) }
|
|
55
|
-
case shard_value
|
|
56
|
-
when Array, ::ActiveRecord::Relation, ::ActiveRecord::Base
|
|
57
|
-
@records = results
|
|
51
|
+
def load(&block)
|
|
52
|
+
if !loaded? || (::Rails.version >= '7.0' && scheduled?)
|
|
53
|
+
@records = activate { |relation| relation.send(:exec_queries, &block) }
|
|
58
54
|
@loaded = true
|
|
59
55
|
end
|
|
60
|
-
|
|
56
|
+
|
|
57
|
+
self
|
|
61
58
|
end
|
|
62
59
|
|
|
63
60
|
%I[update_all delete_all].each do |method|
|
|
64
61
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
65
62
|
def #{method}(*args)
|
|
66
|
-
result = self.activate { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
|
63
|
+
result = self.activate(unordered: true) { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
|
67
64
|
result = result.sum if result.is_a?(Array)
|
|
68
65
|
result
|
|
69
66
|
end
|
|
@@ -94,7 +91,7 @@ module Switchman
|
|
|
94
91
|
|
|
95
92
|
while ids.first.present?
|
|
96
93
|
ids.map!(&:to_i) if is_integer
|
|
97
|
-
ids << ids.first + batch_size if loose_mode
|
|
94
|
+
ids << (ids.first + batch_size) if loose_mode
|
|
98
95
|
|
|
99
96
|
yield(*ids)
|
|
100
97
|
last_value = ids.last
|
|
@@ -103,28 +100,28 @@ module Switchman
|
|
|
103
100
|
end
|
|
104
101
|
end
|
|
105
102
|
|
|
106
|
-
def activate(&block)
|
|
103
|
+
def activate(unordered: false, &block)
|
|
107
104
|
shards = all_shards
|
|
108
105
|
if Array === shards && shards.length == 1
|
|
109
|
-
if shards.first == DefaultShard || shards.first == Shard.current(klass.
|
|
106
|
+
if shards.first == DefaultShard || shards.first == Shard.current(klass.connection_class_for_self)
|
|
110
107
|
yield(self, shards.first)
|
|
111
108
|
else
|
|
112
|
-
shards.first.activate(klass.
|
|
109
|
+
shards.first.activate(klass.connection_class_for_self) { yield(self, shards.first) }
|
|
113
110
|
end
|
|
114
111
|
else
|
|
115
112
|
result_count = 0
|
|
116
113
|
can_order = false
|
|
117
|
-
result = Shard.with_each_shard(shards, [klass.
|
|
114
|
+
result = Shard.with_each_shard(shards, [klass.connection_class_for_self]) do
|
|
118
115
|
# don't even query other shards if we're already past the limit
|
|
119
116
|
next if limit_value && result_count >= limit_value && order_values.empty?
|
|
120
117
|
|
|
121
|
-
relation = shard(Shard.current(klass.
|
|
118
|
+
relation = shard(Shard.current(klass.connection_class_for_self), :to_a)
|
|
122
119
|
# do a minimal query if possible
|
|
123
120
|
relation = relation.limit(limit_value - result_count) if limit_value && !result_count.zero? && order_values.empty?
|
|
124
121
|
|
|
125
122
|
shard_results = relation.activate(&block)
|
|
126
123
|
|
|
127
|
-
if shard_results.present?
|
|
124
|
+
if shard_results.present? && !unordered
|
|
128
125
|
can_order ||= can_order_cross_shard_results? unless order_values.empty?
|
|
129
126
|
raise OrderOnMultiShardQuery if !can_order && !order_values.empty? && result_count.positive?
|
|
130
127
|
|
|
@@ -148,8 +145,12 @@ module Switchman
|
|
|
148
145
|
results.sort! do |l, r|
|
|
149
146
|
result = 0
|
|
150
147
|
order_values.each do |ov|
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
if l.is_a?(::ActiveRecord::Base)
|
|
149
|
+
a = l.attribute(ov.expr.name)
|
|
150
|
+
b = r.attribute(ov.expr.name)
|
|
151
|
+
else
|
|
152
|
+
a, b = l, r
|
|
153
|
+
end
|
|
153
154
|
next if a == b
|
|
154
155
|
|
|
155
156
|
if a.nil? || b.nil?
|
|
@@ -33,12 +33,12 @@ module Switchman
|
|
|
33
33
|
primary_value = params[primary_index]
|
|
34
34
|
target_shard = Shard.local_id_for(primary_value)[1]
|
|
35
35
|
end
|
|
36
|
-
current_shard = Shard.current(klass.
|
|
36
|
+
current_shard = Shard.current(klass.connection_class_for_self)
|
|
37
37
|
target_shard ||= current_shard
|
|
38
38
|
|
|
39
39
|
bind_values = bind_map.bind(params, current_shard, target_shard)
|
|
40
40
|
|
|
41
|
-
target_shard.activate(klass.
|
|
41
|
+
target_shard.activate(klass.connection_class_for_self) do
|
|
42
42
|
sql = qualified_query_builder(target_shard, klass).sql_for(bind_values, connection)
|
|
43
43
|
klass.find_by_sql(sql, bind_values)
|
|
44
44
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Switchman
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
module TestFixtures
|
|
6
|
+
FORBIDDEN_DB_ENVS = %i[development production].freeze
|
|
7
|
+
def setup_fixtures(config = ::ActiveRecord::Base)
|
|
8
|
+
super
|
|
9
|
+
|
|
10
|
+
return unless run_in_transaction?
|
|
11
|
+
|
|
12
|
+
# Replace the one that activerecord natively uses with a switchman-optimized one
|
|
13
|
+
::ActiveSupport::Notifications.unsubscribe(@connection_subscriber)
|
|
14
|
+
# Code adapted from the code in rails proper
|
|
15
|
+
@connection_subscriber = ::ActiveSupport::Notifications.subscribe('!connection.active_record') do |_, _, _, _, payload|
|
|
16
|
+
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
|
17
|
+
shard = payload[:shard] if payload.key?(:shard)
|
|
18
|
+
setup_shared_connection_pool
|
|
19
|
+
|
|
20
|
+
if spec_name && !FORBIDDEN_DB_ENVS.include?(shard)
|
|
21
|
+
begin
|
|
22
|
+
connection = ::ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
|
|
23
|
+
rescue ::ActiveRecord::ConnectionNotEstablished, ::ActiveRecord::NoDatabaseError
|
|
24
|
+
connection = nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if connection && !@fixture_connections.include?(connection)
|
|
28
|
+
connection.begin_transaction joinable: false, _lazy: false
|
|
29
|
+
connection.pool.lock_thread = true if lock_threads
|
|
30
|
+
@fixture_connections << connection
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def enlist_fixture_connections
|
|
37
|
+
setup_shared_connection_pool
|
|
38
|
+
|
|
39
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list.reject { |cp| FORBIDDEN_DB_ENVS.include?(cp.db_config.env_name.to_sym) }.map(&:connection)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -4,6 +4,22 @@ module Switchman
|
|
|
4
4
|
module ActiveSupport
|
|
5
5
|
module Cache
|
|
6
6
|
module ClassMethods
|
|
7
|
+
def lookup_stores(cache_store_config)
|
|
8
|
+
result = {}
|
|
9
|
+
cache_store_config.each do |key, value|
|
|
10
|
+
next if value.is_a?(String)
|
|
11
|
+
|
|
12
|
+
result[key] = ::ActiveSupport::Cache.lookup_store(value)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
cache_store_config.each do |key, value| # rubocop:disable Style/CombinableLoops
|
|
16
|
+
next unless value.is_a?(String)
|
|
17
|
+
|
|
18
|
+
result[key] = result[value]
|
|
19
|
+
end
|
|
20
|
+
result
|
|
21
|
+
end
|
|
22
|
+
|
|
7
23
|
def lookup_store(*store_options)
|
|
8
24
|
store = super
|
|
9
25
|
# can't use defined?, because it's a _ruby_ autoloaded constant,
|
data/lib/switchman/arel.rb
CHANGED
|
@@ -11,22 +11,44 @@ module Switchman
|
|
|
11
11
|
module Visitors
|
|
12
12
|
module ToSql
|
|
13
13
|
# rubocop:disable Naming/MethodName
|
|
14
|
+
# rubocop:disable Naming/MethodParameterName
|
|
14
15
|
|
|
15
|
-
def visit_Arel_Nodes_TableAlias(
|
|
16
|
-
o, collector = args
|
|
16
|
+
def visit_Arel_Nodes_TableAlias(o, collector)
|
|
17
17
|
collector = visit o.relation, collector
|
|
18
18
|
collector << ' '
|
|
19
19
|
collector << quote_local_table_name(o.name)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def visit_Arel_Attributes_Attribute(
|
|
23
|
-
o = args.first
|
|
22
|
+
def visit_Arel_Attributes_Attribute(o, collector)
|
|
24
23
|
join_name = o.relation.table_alias || o.relation.name
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
collector << quote_local_table_name(join_name) << '.' << quote_column_name(o.name)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def visit_Arel_Nodes_HomogeneousIn(o, collector)
|
|
28
|
+
collector.preparable = false
|
|
29
|
+
|
|
30
|
+
collector << quote_local_table_name(o.table_name) << '.' << quote_column_name(o.column_name)
|
|
31
|
+
|
|
32
|
+
collector << if o.type == :in
|
|
33
|
+
' IN ('
|
|
34
|
+
else
|
|
35
|
+
' NOT IN ('
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
values = o.casted_values
|
|
39
|
+
|
|
40
|
+
if values.empty?
|
|
41
|
+
collector << @connection.quote(nil)
|
|
42
|
+
else
|
|
43
|
+
collector.add_binds(values, o.proc_for_binds, &bind_block)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
collector << ')'
|
|
47
|
+
collector
|
|
27
48
|
end
|
|
28
49
|
|
|
29
50
|
# rubocop:enable Naming/MethodName
|
|
51
|
+
# rubocop:enable Naming/MethodParameterName
|
|
30
52
|
|
|
31
53
|
def quote_local_table_name(name)
|
|
32
54
|
return name if ::Arel::Nodes::SqlLiteral === name
|
|
@@ -8,15 +8,12 @@ module Switchman
|
|
|
8
8
|
|
|
9
9
|
class << self
|
|
10
10
|
attr_accessor :creating_new_shard
|
|
11
|
+
attr_reader :all_roles
|
|
11
12
|
|
|
12
13
|
def all
|
|
13
14
|
database_servers.values
|
|
14
15
|
end
|
|
15
16
|
|
|
16
|
-
def all_roles
|
|
17
|
-
@all_roles ||= all.map(&:roles).flatten.uniq
|
|
18
|
-
end
|
|
19
|
-
|
|
20
17
|
def find(id_or_all)
|
|
21
18
|
return all if id_or_all == :all
|
|
22
19
|
return id_or_all.map { |id| database_servers[id || ::Rails.env] }.compact.uniq if id_or_all.is_a?(Array)
|
|
@@ -38,7 +35,7 @@ module Switchman
|
|
|
38
35
|
database_servers[server.id] = server
|
|
39
36
|
::ActiveRecord::Base.configurations.configurations <<
|
|
40
37
|
::ActiveRecord::DatabaseConfigurations::HashConfig.new(::Rails.env, "#{server.id}/primary", settings)
|
|
41
|
-
Shard.send(:
|
|
38
|
+
Shard.send(:configure_connects_to)
|
|
42
39
|
server
|
|
43
40
|
end
|
|
44
41
|
|
|
@@ -49,31 +46,42 @@ module Switchman
|
|
|
49
46
|
servers[rand(servers.length)]
|
|
50
47
|
end
|
|
51
48
|
|
|
49
|
+
def guard_servers
|
|
50
|
+
all.each { |db| db.guard! if db.config[:prefer_secondary] }
|
|
51
|
+
end
|
|
52
|
+
|
|
52
53
|
private
|
|
53
54
|
|
|
54
55
|
def reference_role(role)
|
|
55
56
|
return if all_roles.include?(role)
|
|
56
57
|
|
|
57
58
|
@all_roles << role
|
|
58
|
-
Shard.send(:
|
|
59
|
+
Shard.send(:configure_connects_to)
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
def database_servers
|
|
62
|
-
|
|
63
|
+
if !@database_servers || @database_servers.empty?
|
|
63
64
|
@database_servers = {}.with_indifferent_access
|
|
65
|
+
roles = []
|
|
64
66
|
::ActiveRecord::Base.configurations.configurations.each do |config|
|
|
65
67
|
if config.name.include?('/')
|
|
66
68
|
name, role = config.name.split('/')
|
|
67
69
|
else
|
|
68
70
|
name, role = config.env_name, config.name
|
|
69
71
|
end
|
|
72
|
+
role = role.to_sym
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
roles << role
|
|
75
|
+
if role == :primary
|
|
72
76
|
@database_servers[name] = DatabaseServer.new(config.env_name, config.configuration_hash)
|
|
73
77
|
else
|
|
74
78
|
@database_servers[name].roles << role
|
|
75
79
|
end
|
|
76
80
|
end
|
|
81
|
+
# Do this after so that all database servers for all roles are established and we won't prematurely
|
|
82
|
+
# configure a connection for the wrong role
|
|
83
|
+
@all_roles = roles.uniq
|
|
84
|
+
Shard.send(:configure_connects_to)
|
|
77
85
|
end
|
|
78
86
|
@database_servers
|
|
79
87
|
end
|
|
@@ -89,13 +97,13 @@ module Switchman
|
|
|
89
97
|
end
|
|
90
98
|
|
|
91
99
|
def connects_to_hash
|
|
92
|
-
self.class.all_roles.
|
|
100
|
+
self.class.all_roles.to_h do |role|
|
|
93
101
|
config_role = role
|
|
94
102
|
config_role = :primary unless roles.include?(role)
|
|
95
103
|
config_name = :"#{id}/#{config_role}"
|
|
96
104
|
config_name = :primary if id == ::Rails.env && config_role == :primary
|
|
97
105
|
[role.to_sym, config_name]
|
|
98
|
-
end
|
|
106
|
+
end
|
|
99
107
|
end
|
|
100
108
|
|
|
101
109
|
def destroy
|
|
@@ -129,27 +137,27 @@ module Switchman
|
|
|
129
137
|
end
|
|
130
138
|
end
|
|
131
139
|
|
|
132
|
-
def guard_rail_environment
|
|
133
|
-
@guard_rail_environment || ::GuardRail.environment
|
|
134
|
-
end
|
|
135
|
-
|
|
136
140
|
# locks this db to a specific environment, except for
|
|
137
141
|
# when doing writes (then it falls back to the current
|
|
138
142
|
# value of GuardRail.environment)
|
|
139
143
|
def guard!(environment = :secondary)
|
|
140
|
-
|
|
144
|
+
DatabaseServer.send(:reference_role, environment)
|
|
145
|
+
::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => environment }, klasses: [::ActiveRecord::Base] }
|
|
141
146
|
end
|
|
142
147
|
|
|
143
148
|
def unguard!
|
|
144
|
-
|
|
149
|
+
::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => :_switchman_inherit }, klasses: [::ActiveRecord::Base] }
|
|
145
150
|
end
|
|
146
151
|
|
|
147
152
|
def unguard
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
return yield unless ::ActiveRecord::Base.role_overriden?(id.to_sym)
|
|
154
|
+
|
|
155
|
+
begin
|
|
156
|
+
unguard!
|
|
157
|
+
yield
|
|
158
|
+
ensure
|
|
159
|
+
::ActiveRecord::Base.connected_to_stack.pop
|
|
160
|
+
end
|
|
153
161
|
end
|
|
154
162
|
|
|
155
163
|
def shards
|
|
@@ -186,58 +194,56 @@ module Switchman
|
|
|
186
194
|
|
|
187
195
|
name ||= "#{config[:database]}_shard_#{id}"
|
|
188
196
|
|
|
197
|
+
schema_already_existed = false
|
|
198
|
+
shard = nil
|
|
189
199
|
Shard.connection.transaction do
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if ::ActiveRecord::Base.connection.select_value("SELECT 1 FROM pg_namespace WHERE nspname=#{::ActiveRecord::Base.connection.quote(name)}")
|
|
201
|
-
schema_already_existed = true
|
|
202
|
-
raise 'This schema already exists; cannot overwrite'
|
|
203
|
-
end
|
|
204
|
-
Array(create_statement.call).each do |stmt|
|
|
205
|
-
::ActiveRecord::Base.connection.execute(stmt)
|
|
206
|
-
end
|
|
200
|
+
self.class.creating_new_shard = true
|
|
201
|
+
DatabaseServer.send(:reference_role, :deploy)
|
|
202
|
+
::ActiveRecord::Base.connected_to(shard: self.id.to_sym, role: :deploy) do
|
|
203
|
+
shard = Shard.create!(id: id,
|
|
204
|
+
name: name,
|
|
205
|
+
database_server_id: self.id)
|
|
206
|
+
if create_statement
|
|
207
|
+
if ::ActiveRecord::Base.connection.select_value("SELECT 1 FROM pg_namespace WHERE nspname=#{::ActiveRecord::Base.connection.quote(name)}")
|
|
208
|
+
schema_already_existed = true
|
|
209
|
+
raise 'This schema already exists; cannot overwrite'
|
|
207
210
|
end
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
Array(create_statement.call).each do |stmt|
|
|
212
|
+
::ActiveRecord::Base.connection.execute(stmt)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
if config[:adapter] == 'postgresql'
|
|
216
|
+
old_proc = ::ActiveRecord::Base.connection.raw_connection.set_notice_processor do
|
|
211
217
|
end
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
reset_column_information
|
|
223
|
-
::ActiveRecord::Base.descendants.reject do |m|
|
|
224
|
-
m <= UnshardedRecord || !m.table_exists?
|
|
225
|
-
end.each(&:define_attribute_methods)
|
|
218
|
+
end
|
|
219
|
+
old_verbose = ::ActiveRecord::Migration.verbose
|
|
220
|
+
::ActiveRecord::Migration.verbose = false
|
|
221
|
+
|
|
222
|
+
unless schema == false
|
|
223
|
+
shard.activate do
|
|
224
|
+
reset_column_information
|
|
225
|
+
|
|
226
|
+
::ActiveRecord::Base.connection.transaction(requires_new: true) do
|
|
227
|
+
::ActiveRecord::Base.connection.migration_context.migrate
|
|
226
228
|
end
|
|
229
|
+
reset_column_information
|
|
230
|
+
::ActiveRecord::Base.descendants.reject do |m|
|
|
231
|
+
m <= UnshardedRecord || !m.table_exists?
|
|
232
|
+
end.each(&:define_attribute_methods)
|
|
227
233
|
end
|
|
228
|
-
ensure
|
|
229
|
-
::ActiveRecord::Migration.verbose = old_verbose
|
|
230
|
-
::ActiveRecord::Base.connection.raw_connection.set_notice_processor(&old_proc) if old_proc
|
|
231
234
|
end
|
|
232
|
-
shard
|
|
233
|
-
rescue
|
|
234
|
-
shard.destroy
|
|
235
|
-
shard.drop_database rescue nil unless schema_already_existed
|
|
236
|
-
reset_column_information unless schema == false rescue nil
|
|
237
|
-
raise
|
|
238
235
|
ensure
|
|
239
|
-
|
|
236
|
+
::ActiveRecord::Migration.verbose = old_verbose
|
|
237
|
+
::ActiveRecord::Base.connection.raw_connection.set_notice_processor(&old_proc) if old_proc
|
|
240
238
|
end
|
|
239
|
+
shard
|
|
240
|
+
rescue
|
|
241
|
+
shard&.destroy
|
|
242
|
+
shard&.drop_database rescue nil unless schema_already_existed
|
|
243
|
+
reset_column_information unless schema == false rescue nil
|
|
244
|
+
raise
|
|
245
|
+
ensure
|
|
246
|
+
self.class.creating_new_shard = false
|
|
241
247
|
end
|
|
242
248
|
end
|
|
243
249
|
|