switchman 3.0.0 → 3.0.5
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/app/models/switchman/shard.rb +1 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
- data/lib/switchman.rb +2 -0
- data/lib/switchman/active_record/association.rb +1 -1
- data/lib/switchman/active_record/attribute_methods.rb +48 -0
- data/lib/switchman/active_record/calculations.rb +1 -1
- data/lib/switchman/active_record/migration.rb +13 -1
- data/lib/switchman/active_record/postgresql_adapter.rb +26 -110
- data/lib/switchman/active_record/predicate_builder.rb +1 -1
- data/lib/switchman/active_record/query_methods.rb +13 -3
- data/lib/switchman/active_record/relation.rb +56 -5
- data/lib/switchman/database_server.rb +2 -3
- data/lib/switchman/engine.rb +1 -0
- data/lib/switchman/test_helper.rb +1 -1
- data/lib/switchman/version.rb +1 -1
- metadata +3 -4
- data/lib/switchman/schema_cache.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3f9894955745b77bd418c8cede4882f5f37bf8cd3c0e2a3eecd53baa8658e1a
|
4
|
+
data.tar.gz: d160939ff0c15d4c57b0836abe0850e9c8a499fc05eb410932dc038d2835c60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89dc3d801b5f97d2147f10bcfb691279395590b45e9631103c73f66e487345e8608e185c07f5e54429bf43d29bd3f35c017bd93cd9354a88e29d0456d1d5040f
|
7
|
+
data.tar.gz: 9893296f2801ded4b1e227a4672b0e474735d2c6ba4ff7f5e95d0591b753659a97066f422ca0615d8abbd4c1e5f9bd4c8250ff9c3c697fcb18640b3ff47dd219
|
data/lib/switchman.rb
CHANGED
@@ -85,7 +85,7 @@ module Switchman
|
|
85
85
|
# Copypasta from Activerecord but with added global_id_for goodness.
|
86
86
|
def records_for(ids)
|
87
87
|
scope.where(association_key_name => ids).load do |record|
|
88
|
-
global_key = if
|
88
|
+
global_key = if model.connection_classes == UnshardedRecord
|
89
89
|
convert_key(record[association_key_name])
|
90
90
|
else
|
91
91
|
Shard.global_id_for(record[association_key_name], record.shard)
|
@@ -141,6 +141,54 @@ module Switchman
|
|
141
141
|
self.class.define_attribute_methods
|
142
142
|
super
|
143
143
|
end
|
144
|
+
|
145
|
+
# these are called if the specific methods haven't been defined yet
|
146
|
+
def attribute(attr_name)
|
147
|
+
return super unless self.class.sharded_column?(attr_name)
|
148
|
+
|
149
|
+
reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
|
150
|
+
::Switchman::Shard.relative_id_for(super, shard, ::Switchman::Shard.current(connection_classes_for_reflection(reflection)))
|
151
|
+
end
|
152
|
+
|
153
|
+
def attribute=(attr_name, new_value)
|
154
|
+
unless self.class.sharded_column?(attr_name)
|
155
|
+
super
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
|
160
|
+
super(::Switchman::Shard.relative_id_for(new_value, ::Switchman::Shard.current(connection_classes_for_reflection(reflection)), shard))
|
161
|
+
end
|
162
|
+
|
163
|
+
def global_attribute(attr_name)
|
164
|
+
if self.class.sharded_column?(attr_name)
|
165
|
+
::Switchman::Shard.global_id_for(attribute(attr_name), shard)
|
166
|
+
else
|
167
|
+
attribute(attr_name)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def local_attribute(attr_name)
|
172
|
+
if self.class.sharded_column?(attr_name)
|
173
|
+
::Switchman::Shard.local_id_for(attribute(attr_name), shard).first
|
174
|
+
else
|
175
|
+
attribute(attr_name)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def connection_classes_for_reflection(reflection)
|
182
|
+
if reflection
|
183
|
+
if reflection.options[:polymorphic]
|
184
|
+
read_attribute(reflection.foreign_type)&.constantize&.connection_classes
|
185
|
+
else
|
186
|
+
reflection.klass.connection_classes
|
187
|
+
end
|
188
|
+
else
|
189
|
+
self.class.connection_classes
|
190
|
+
end
|
191
|
+
end
|
144
192
|
end
|
145
193
|
end
|
146
194
|
end
|
@@ -50,7 +50,7 @@ module Switchman
|
|
50
50
|
|
51
51
|
def calculate_simple_average(column_name, distinct)
|
52
52
|
# See activerecord#execute_simple_calculation
|
53
|
-
relation =
|
53
|
+
relation = except(:order)
|
54
54
|
column = aggregate_column(column_name)
|
55
55
|
relation.select_values = [operation_over_aggregate_column(column, 'average', distinct).as('average'),
|
56
56
|
operation_over_aggregate_column(column, 'count', distinct).as('count')]
|
@@ -20,10 +20,22 @@ module Switchman
|
|
20
20
|
end
|
21
21
|
|
22
22
|
module Migrator
|
23
|
+
# significant change: hash shard name, not database name
|
23
24
|
def generate_migrator_advisory_lock_id
|
24
|
-
shard_name_hash = Zlib.crc32(
|
25
|
+
shard_name_hash = Zlib.crc32(Shard.current.name)
|
25
26
|
::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
|
26
27
|
end
|
28
|
+
|
29
|
+
# significant change: strip out prefer_secondary from config
|
30
|
+
def with_advisory_lock_connection
|
31
|
+
pool = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
32
|
+
::ActiveRecord::Base.connection_db_config.configuration_hash.except(:prefer_secondary)
|
33
|
+
)
|
34
|
+
|
35
|
+
pool.with_connection { |connection| yield(connection) } # rubocop:disable Style/ExplicitBlockArgument
|
36
|
+
ensure
|
37
|
+
pool&.disconnect!
|
38
|
+
end
|
27
39
|
end
|
28
40
|
|
29
41
|
module MigrationContext
|
@@ -40,89 +40,36 @@ module Switchman
|
|
40
40
|
select_values('SELECT * FROM unnest(current_schemas(false))')
|
41
41
|
end
|
42
42
|
|
43
|
-
def tables(_name = nil)
|
44
|
-
query(<<-SQL, 'SCHEMA').map { |row| row[0] }
|
45
|
-
SELECT tablename
|
46
|
-
FROM pg_tables
|
47
|
-
WHERE schemaname = '#{shard.name}'
|
48
|
-
SQL
|
49
|
-
end
|
50
|
-
|
51
43
|
def extract_schema_qualified_name(string)
|
52
44
|
name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
|
53
45
|
name.instance_variable_set(:@schema, shard.name) if string && !name.schema
|
54
46
|
[name.schema, name.identifier]
|
55
47
|
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
result = query(<<-SQL, 'SCHEMA')
|
75
|
-
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
76
|
-
FROM pg_class t
|
77
|
-
INNER JOIN pg_index d ON t.oid = d.indrelid
|
78
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
79
|
-
WHERE i.relkind = 'i'
|
80
|
-
AND d.indisprimary = 'f'
|
81
|
-
AND t.relname = '#{table_name}'
|
82
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
83
|
-
ORDER BY i.relname
|
84
|
-
SQL
|
85
|
-
|
86
|
-
result.map do |row|
|
87
|
-
index_name = row[0]
|
88
|
-
unique = row[1] == true || row[1] == 't'
|
89
|
-
indkey = row[2].split
|
90
|
-
inddef = row[3]
|
91
|
-
oid = row[4]
|
92
|
-
|
93
|
-
columns = Hash[query(<<-SQL, 'SCHEMA')] # rubocop:disable Style/HashConversion
|
94
|
-
SELECT a.attnum, a.attname
|
95
|
-
FROM pg_attribute a
|
96
|
-
WHERE a.attrelid = #{oid}
|
97
|
-
AND a.attnum IN (#{indkey.join(',')})
|
98
|
-
SQL
|
99
|
-
|
100
|
-
column_names = columns.stringify_keys.values_at(*indkey).compact
|
101
|
-
|
102
|
-
next if column_names.empty?
|
103
|
-
|
104
|
-
# add info on sort order for columns (only desc order is explicitly specified, asc is the default)
|
105
|
-
desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
|
106
|
-
orders = desc_order_columns.any? ? Hash[desc_order_columns.map { |order_column| [order_column, :desc] }] : {} # rubocop:disable Style/HashConversion
|
107
|
-
where = inddef.scan(/WHERE (.+)$/).flatten[0]
|
108
|
-
using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
|
109
|
-
|
110
|
-
::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names,
|
111
|
-
orders: orders, where: where, using: using)
|
112
|
-
end.compact
|
49
|
+
# significant change: use the shard name if no explicit schema
|
50
|
+
def quoted_scope(name = nil, type: nil)
|
51
|
+
schema, name = extract_schema_qualified_name(name)
|
52
|
+
type = \
|
53
|
+
case type # rubocop:disable Style/HashLikeCase
|
54
|
+
when 'BASE TABLE'
|
55
|
+
"'r','p'"
|
56
|
+
when 'VIEW'
|
57
|
+
"'v','m'"
|
58
|
+
when 'FOREIGN TABLE'
|
59
|
+
"'f'"
|
60
|
+
end
|
61
|
+
scope = {}
|
62
|
+
scope[:schema] = quote(schema || shard.name)
|
63
|
+
scope[:name] = quote(name) if name
|
64
|
+
scope[:type] = type if type
|
65
|
+
scope
|
113
66
|
end
|
114
67
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
121
|
-
WHERE i.relkind = 'i'
|
122
|
-
AND i.relname = '#{index_name}'
|
123
|
-
AND t.relname = '#{table_name}'
|
124
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
|
125
|
-
SQL
|
68
|
+
def foreign_keys(table_name)
|
69
|
+
super.each do |fk|
|
70
|
+
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
|
71
|
+
fk.to_table = to_table_qualified_name.identifier if to_table_qualified_name.schema == shard.name
|
72
|
+
end
|
126
73
|
end
|
127
74
|
|
128
75
|
def quote_local_table_name(name)
|
@@ -140,6 +87,10 @@ module Switchman
|
|
140
87
|
name.quoted
|
141
88
|
end
|
142
89
|
|
90
|
+
def with_global_table_name(&block)
|
91
|
+
with_local_table_name(false, &block)
|
92
|
+
end
|
93
|
+
|
143
94
|
def with_local_table_name(enable = true) # rubocop:disable Style/OptionalBooleanParameter
|
144
95
|
old_value = @use_local_table_name
|
145
96
|
@use_local_table_name = enable
|
@@ -148,41 +99,6 @@ module Switchman
|
|
148
99
|
@use_local_table_name = old_value
|
149
100
|
end
|
150
101
|
|
151
|
-
def foreign_keys(table_name)
|
152
|
-
# mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
|
153
|
-
fk_info = select_all <<-SQL.strip_heredoc
|
154
|
-
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
155
|
-
FROM pg_constraint c
|
156
|
-
JOIN pg_class t1 ON c.conrelid = t1.oid
|
157
|
-
JOIN pg_class t2 ON c.confrelid = t2.oid
|
158
|
-
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
159
|
-
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
160
|
-
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
161
|
-
WHERE c.contype = 'f'
|
162
|
-
AND t1.relname = #{quote(table_name)}
|
163
|
-
AND t3.nspname = '#{shard.name}'
|
164
|
-
ORDER BY c.conname
|
165
|
-
SQL
|
166
|
-
|
167
|
-
fk_info.map do |row|
|
168
|
-
options = {
|
169
|
-
column: row['column'],
|
170
|
-
name: row['name'],
|
171
|
-
primary_key: row['primary_key']
|
172
|
-
}
|
173
|
-
|
174
|
-
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
|
175
|
-
options[:on_update] = extract_foreign_key_action(row['on_update'])
|
176
|
-
|
177
|
-
# strip the schema name from to_table if it matches
|
178
|
-
to_table = row['to_table']
|
179
|
-
to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
|
180
|
-
to_table = to_table_qualified_name.identifier if to_table_qualified_name.schema == shard.name
|
181
|
-
|
182
|
-
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
102
|
def add_index_options(_table_name, _column_name, **)
|
187
103
|
index, algorithm, if_not_exists = super
|
188
104
|
algorithm = nil if DatabaseServer.creating_new_shard && algorithm == 'CONCURRENTLY'
|
@@ -239,6 +239,10 @@ module Switchman
|
|
239
239
|
connection.with_local_table_name { super }
|
240
240
|
end
|
241
241
|
|
242
|
+
def table_name_matches?(from)
|
243
|
+
connection.with_global_table_name { super }
|
244
|
+
end
|
245
|
+
|
242
246
|
def transpose_predicates(predicates,
|
243
247
|
source_shard,
|
244
248
|
target_shard,
|
@@ -281,7 +285,7 @@ module Switchman
|
|
281
285
|
remove = true if type == :primary &&
|
282
286
|
remove_nonlocal_primary_keys &&
|
283
287
|
predicate.left.relation.klass == klass &&
|
284
|
-
predicate.is_a?(::Arel::Nodes::Equality)
|
288
|
+
(predicate.is_a?(::Arel::Nodes::Equality) || predicate.is_a?(::Arel::Nodes::HomogeneousIn))
|
285
289
|
|
286
290
|
current_source_shard =
|
287
291
|
if source_shard
|
@@ -301,7 +305,7 @@ module Switchman
|
|
301
305
|
new_right_value =
|
302
306
|
case right
|
303
307
|
when Array
|
304
|
-
right.map { |val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove) }
|
308
|
+
right.map { |val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove).presence }.compact
|
305
309
|
else
|
306
310
|
transpose_predicate_value(right, current_source_shard, target_shard, type, remove)
|
307
311
|
end
|
@@ -315,7 +319,13 @@ module Switchman
|
|
315
319
|
predicate.class.new(predicate.left, right.class.new(new_right_value, right.attribute))
|
316
320
|
end
|
317
321
|
elsif predicate.is_a?(::Arel::Nodes::HomogeneousIn)
|
318
|
-
|
322
|
+
# switch to a regular In, so that Relation::WhereClause#contradiction? knows about it
|
323
|
+
if new_right_value.empty?
|
324
|
+
klass = predicate.type == :in ? ::Arel::Nodes::In : ::Arel::Nodes::NotIn
|
325
|
+
klass.new(predicate.attribute, new_right_value)
|
326
|
+
else
|
327
|
+
predicate.class.new(new_right_value, predicate.attribute, predicate.type)
|
328
|
+
end
|
319
329
|
else
|
320
330
|
predicate.class.new(predicate.left, new_right_value)
|
321
331
|
end
|
@@ -63,7 +63,7 @@ module Switchman
|
|
63
63
|
%I[update_all delete_all].each do |method|
|
64
64
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
65
65
|
def #{method}(*args)
|
66
|
-
result = self.activate { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
66
|
+
result = self.activate(unordered: true) { |relation| relation.call_super(#{method.inspect}, Relation, *args) }
|
67
67
|
result = result.sum if result.is_a?(Array)
|
68
68
|
result
|
69
69
|
end
|
@@ -103,7 +103,7 @@ module Switchman
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
def activate(&block)
|
106
|
+
def activate(unordered: false, &block)
|
107
107
|
shards = all_shards
|
108
108
|
if Array === shards && shards.length == 1
|
109
109
|
if shards.first == DefaultShard || shards.first == Shard.current(klass.connection_classes)
|
@@ -112,10 +112,61 @@ module Switchman
|
|
112
112
|
shards.first.activate(klass.connection_classes) { yield(self, shards.first) }
|
113
113
|
end
|
114
114
|
else
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
result_count = 0
|
116
|
+
can_order = false
|
117
|
+
result = Shard.with_each_shard(shards, [klass.connection_classes]) do
|
118
|
+
# don't even query other shards if we're already past the limit
|
119
|
+
next if limit_value && result_count >= limit_value && order_values.empty?
|
120
|
+
|
121
|
+
relation = shard(Shard.current(klass.connection_classes), :to_a)
|
122
|
+
# do a minimal query if possible
|
123
|
+
relation = relation.limit(limit_value - result_count) if limit_value && !result_count.zero? && order_values.empty?
|
124
|
+
|
125
|
+
shard_results = relation.activate(&block)
|
126
|
+
|
127
|
+
if shard_results.present? && !unordered
|
128
|
+
can_order ||= can_order_cross_shard_results? unless order_values.empty?
|
129
|
+
raise OrderOnMultiShardQuery if !can_order && !order_values.empty? && result_count.positive?
|
130
|
+
|
131
|
+
result_count += shard_results.is_a?(Array) ? shard_results.length : 1
|
132
|
+
end
|
133
|
+
shard_results
|
134
|
+
end
|
135
|
+
|
136
|
+
result = reorder_cross_shard_results(result) if can_order
|
137
|
+
result.slice!(limit_value..-1) if limit_value
|
138
|
+
result
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def can_order_cross_shard_results?
|
143
|
+
# we only presume to be able to post-sort the most basic of orderings
|
144
|
+
order_values.all? { |ov| ov.is_a?(::Arel::Nodes::Ordering) && ov.expr.is_a?(::Arel::Attributes::Attribute) }
|
145
|
+
end
|
146
|
+
|
147
|
+
def reorder_cross_shard_results(results)
|
148
|
+
results.sort! do |l, r|
|
149
|
+
result = 0
|
150
|
+
order_values.each do |ov|
|
151
|
+
if l.is_a?(::ActiveRecord::Base)
|
152
|
+
a = l.attribute(ov.expr.name)
|
153
|
+
b = r.attribute(ov.expr.name)
|
154
|
+
else
|
155
|
+
a, b = l, r
|
156
|
+
end
|
157
|
+
next if a == b
|
158
|
+
|
159
|
+
if a.nil? || b.nil?
|
160
|
+
result = 1 if a.nil?
|
161
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
162
|
+
else
|
163
|
+
result = a <=> b
|
164
|
+
end
|
165
|
+
|
166
|
+
result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
|
167
|
+
break unless result.zero?
|
118
168
|
end
|
169
|
+
result
|
119
170
|
end
|
120
171
|
end
|
121
172
|
end
|
@@ -113,7 +113,7 @@ module Switchman
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def config(environment = :primary)
|
116
|
-
@configs[environment] ||=
|
116
|
+
@configs[environment] ||=
|
117
117
|
case @config[environment]
|
118
118
|
when Array
|
119
119
|
@config[environment].map do |config|
|
@@ -127,7 +127,6 @@ module Switchman
|
|
127
127
|
else
|
128
128
|
@config
|
129
129
|
end
|
130
|
-
end
|
131
130
|
end
|
132
131
|
|
133
132
|
def guard_rail_environment
|
@@ -214,7 +213,7 @@ module Switchman
|
|
214
213
|
::ActiveRecord::Migration.verbose = false
|
215
214
|
|
216
215
|
unless schema == false
|
217
|
-
shard.activate do
|
216
|
+
shard.activate(*Shard.sharded_models) do
|
218
217
|
reset_column_information
|
219
218
|
|
220
219
|
::ActiveRecord::Base.connection.transaction(requires_new: true) do
|
data/lib/switchman/engine.rb
CHANGED
@@ -150,6 +150,7 @@ module Switchman
|
|
150
150
|
::ActiveRecord::Relation.include(CallSuper)
|
151
151
|
|
152
152
|
::ActiveRecord::PredicateBuilder::AssociationQueryValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
|
153
|
+
::ActiveRecord::PredicateBuilder::PolymorphicArrayValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
|
153
154
|
|
154
155
|
::ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(ActiveRecord::Tasks::DatabaseTasks)
|
155
156
|
|
@@ -19,7 +19,7 @@ module Switchman
|
|
19
19
|
end
|
20
20
|
|
21
21
|
server1 = Shard.default.database_server
|
22
|
-
server2 = DatabaseServer.create(Shard.default.database_server.config)
|
22
|
+
server2 = DatabaseServer.create(Shard.default.database_server.config.merge(server2: true))
|
23
23
|
|
24
24
|
if server1 == Shard.default.database_server && server1.config[:shard1] && server1.config[:shard2]
|
25
25
|
# look for the shards in the db already
|
data/lib/switchman/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: switchman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-06-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -289,7 +289,6 @@ files:
|
|
289
289
|
- lib/switchman/open4.rb
|
290
290
|
- lib/switchman/r_spec_helper.rb
|
291
291
|
- lib/switchman/rails.rb
|
292
|
-
- lib/switchman/schema_cache.rb
|
293
292
|
- lib/switchman/sharded_instrumenter.rb
|
294
293
|
- lib/switchman/standard_error.rb
|
295
294
|
- lib/switchman/test_helper.rb
|
@@ -314,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
314
313
|
- !ruby/object:Gem::Version
|
315
314
|
version: '0'
|
316
315
|
requirements: []
|
317
|
-
rubygems_version: 3.
|
316
|
+
rubygems_version: 3.2.15
|
318
317
|
signing_key:
|
319
318
|
specification_version: 4
|
320
319
|
summary: Rails sharding magic
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Switchman
|
4
|
-
class SchemaCache < ::ActiveRecord::ConnectionAdapters::SchemaCache
|
5
|
-
delegate :connection, to: :pool
|
6
|
-
attr_reader :pool
|
7
|
-
|
8
|
-
def initialize(pool)
|
9
|
-
@pool = pool
|
10
|
-
super(nil)
|
11
|
-
end
|
12
|
-
|
13
|
-
def copy_values(other_cache)
|
14
|
-
# use the same cached values but still fall back to the correct pool
|
15
|
-
%i[@columns @columns_hash @primary_keys @data_sources].each do |iv|
|
16
|
-
instance_variable_set(iv, other_cache.instance_variable_get(iv))
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|