switchman 2.0.6 → 2.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9dc22c0bf7a00cd1591602240e782813882155b744fa682a26ac20201a45c0e6
4
- data.tar.gz: fe72352d11d0e81e6e216ba028578c5a4b0f8600fb603f2d5100f99dd4d54721
3
+ metadata.gz: aa20d460683c12b9e6528f0956c83dec5fadcc4247d551fbd84361757d5452a0
4
+ data.tar.gz: 79a6a917b940d6e0bc5b10288f757d002635526e083f3c123698976fb5e96483
5
5
  SHA512:
6
- metadata.gz: 2311f1ad0547735b6ffa51b18790564b67db99009b1ca4d0080eec7e881dd5e735e745dc6c78c0a5f26b8ca2ef0bc9afeaa5c9fe6cfac0aa882f5c3cb8c7d82c
7
- data.tar.gz: 6b2f5e2cab99c42d5358c464e22a0dd267a2b66108e3e62f252970735d1482618460b37fc730ec4be2bdeb791e33bb6549ebc939ec9714f4fad21a48bcb01108
6
+ metadata.gz: 55aca398595c2fda0e32f4aa35e10f42ded64d3154d1dd9bb5cee8f0a0682d61317f8486b156e2722ed3c381dd6cc42710729e19d859b3ade543991469464835
7
+ data.tar.gz: 4b5bfb169f36aa3a69f716195316941f648d8b06ae3c9a9f09c5b5835dd67005ddbc7fe7cbe864b278aefeb3abdeaa8f65292f00dcd29c4cf1011c4e852bec64
@@ -718,6 +718,7 @@ module Switchman
718
718
  Switchman.cache.delete(['shard', id].join('/'))
719
719
  Switchman.cache.delete("default_shard") if default?
720
720
  end
721
+ self.class.clear_cache
721
722
  end
722
723
 
723
724
  def default_name
@@ -10,6 +10,6 @@ class AddDefaultShardIndex < ActiveRecord::Migration[4.2]
10
10
  else
11
11
  {}
12
12
  end
13
- add_index :switchman_shards, :default, options
13
+ add_index :switchman_shards, :default, **options
14
14
  end
15
15
  end
data/lib/switchman.rb CHANGED
@@ -17,4 +17,6 @@ module Switchman
17
17
  def self.cache=(cache)
18
18
  @cache = cache
19
19
  end
20
+
21
+ class OrderOnMultiShardQuery < RuntimeError; end
20
22
  end
@@ -87,7 +87,7 @@ module Switchman
87
87
  # Copypasta from Activerecord but with added global_id_for goodness.
88
88
  def records_for(ids)
89
89
  scope.where(association_key_name => ids).load do |record|
90
- global_key = if record.class.shard_category == :unsharded
90
+ global_key = if model.shard_category == :unsharded
91
91
  convert_key(record[association_key_name])
92
92
  else
93
93
  Shard.global_id_for(record[association_key_name], record.shard)
@@ -51,7 +51,7 @@ module Switchman
51
51
 
52
52
  def calculate_simple_average(column_name, distinct)
53
53
  # See activerecord#execute_simple_calculation
54
- relation = reorder(nil)
54
+ relation = except(:order)
55
55
  column = aggregate_column(column_name)
56
56
  relation.select_values = [operation_over_aggregate_column(column, "average", distinct).as("average"),
57
57
  operation_over_aggregate_column(column, "count", distinct).as("count")]
@@ -135,7 +135,7 @@ module Switchman
135
135
  primary_pool = retrieve_connection_pool("primary")
136
136
  if primary_pool.is_a?(ConnectionPoolProxy)
137
137
  pool = ConnectionPoolProxy.new(spec_name.to_sym, primary_pool.default_pool, @shard_connection_pools)
138
- pool.schema_cache.copy_values(primary_pool.schema_cache)
138
+ pool.schema_cache.copy_references(primary_pool.schema_cache)
139
139
  pool
140
140
  else
141
141
  primary_pool
@@ -30,10 +30,42 @@ module Switchman
30
30
  end
31
31
 
32
32
  module Migrator
33
+ # significant change: hash shard id, not database name
33
34
  def generate_migrator_advisory_lock_id
34
- shard_name_hash = Zlib.crc32("#{Shard.current.id}:#{Shard.current.name}")
35
+ shard_name_hash = Zlib.crc32(Shard.current.name)
35
36
  ::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
36
37
  end
38
+
39
+ if ::Rails.version >= '6.0'
40
+ # copy/paste from Rails 6.1
41
+ def with_advisory_lock
42
+ lock_id = generate_migrator_advisory_lock_id
43
+
44
+ with_advisory_lock_connection do |connection|
45
+ got_lock = connection.get_advisory_lock(lock_id)
46
+ raise ::ActiveRecord::ConcurrentMigrationError unless got_lock
47
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
48
+ yield
49
+ ensure
50
+ if got_lock && !connection.release_advisory_lock(lock_id)
51
+ raise ::ActiveRecord::ConcurrentMigrationError.new(
52
+ ::ActiveRecord::ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
53
+ )
54
+ end
55
+ end
56
+ end
57
+
58
+ # significant change: strip out prefer_secondary from config
59
+ def with_advisory_lock_connection
60
+ pool = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
61
+ ::ActiveRecord::Base.connection_config.except(:prefer_secondary)
62
+ )
63
+
64
+ pool.with_connection { |connection| yield(connection) }
65
+ ensure
66
+ pool&.disconnect!
67
+ end
68
+ end
37
69
  end
38
70
 
39
71
  module MigrationContext
@@ -40,14 +40,6 @@ 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
  if string && !name.schema
@@ -56,80 +48,155 @@ module Switchman
56
48
  [name.schema, name.identifier]
57
49
  end
58
50
 
59
- def view_exists?(name)
60
- name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
61
- return false unless name.identifier
62
- if !name.schema
63
- name.instance_variable_set(:@schema, shard.name)
64
- end
65
-
66
- select_values(<<-SQL, 'SCHEMA').any?
67
- SELECT c.relname
68
- FROM pg_class c
69
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
70
- WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
71
- AND c.relname = '#{name.identifier}'
72
- AND n.nspname = '#{shard.name}'
73
- SQL
51
+ # significant change: use the shard name if no explicit schema
52
+ def quoted_scope(name = nil, type: nil)
53
+ schema, name = extract_schema_qualified_name(name)
54
+ type = \
55
+ case type
56
+ when "BASE TABLE"
57
+ "'r','p'"
58
+ when "VIEW"
59
+ "'v','m'"
60
+ when "FOREIGN TABLE"
61
+ "'f'"
62
+ end
63
+ scope = {}
64
+ scope[:schema] = quote(schema || shard.name)
65
+ scope[:name] = quote(name) if name
66
+ scope[:type] = type if type
67
+ scope
74
68
  end
75
69
 
76
- def indexes(table_name)
77
- result = query(<<-SQL, 'SCHEMA')
78
- SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
79
- FROM pg_class t
80
- INNER JOIN pg_index d ON t.oid = d.indrelid
81
- INNER JOIN pg_class i ON d.indexrelid = i.oid
82
- WHERE i.relkind = 'i'
83
- AND d.indisprimary = 'f'
84
- AND t.relname = '#{table_name}'
85
- AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
86
- ORDER BY i.relname
87
- SQL
88
-
89
-
90
- result.map do |row|
91
- index_name = row[0]
92
- unique = row[1] == true || row[1] == 't'
93
- indkey = row[2].split(" ")
94
- inddef = row[3]
95
- oid = row[4]
96
-
97
- columns = Hash[query(<<-SQL, "SCHEMA")]
98
- SELECT a.attnum, a.attname
99
- FROM pg_attribute a
100
- WHERE a.attrelid = #{oid}
101
- AND a.attnum IN (#{indkey.join(",")})
70
+ if ::Rails.version < '6.0'
71
+ def tables(name = nil)
72
+ query(<<-SQL, 'SCHEMA').map { |row| row[0] }
73
+ SELECT tablename
74
+ FROM pg_tables
75
+ WHERE schemaname = '#{shard.name}'
102
76
  SQL
77
+ end
103
78
 
104
- column_names = columns.stringify_keys.values_at(*indkey).compact
105
-
106
- unless column_names.empty?
107
- # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
108
- desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
109
- orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
110
- where = inddef.scan(/WHERE (.+)$/).flatten[0]
111
- using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
112
-
113
- if ::Rails.version >= "5.2"
114
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders, where: where, using: using)
115
- else
116
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
117
- end
79
+ def view_exists?(name)
80
+ name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
81
+ return false unless name.identifier
82
+ if !name.schema
83
+ name.instance_variable_set(:@schema, shard.name)
118
84
  end
119
- end.compact
120
- end
121
85
 
122
- def index_name_exists?(table_name, index_name, _default = nil)
123
- exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
124
- SELECT COUNT(*)
86
+ select_values(<<-SQL, 'SCHEMA').any?
87
+ SELECT c.relname
88
+ FROM pg_class c
89
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
90
+ WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
91
+ AND c.relname = '#{name.identifier}'
92
+ AND n.nspname = '#{shard.name}'
93
+ SQL
94
+ end
95
+
96
+ def indexes(table_name)
97
+ result = query(<<-SQL, 'SCHEMA')
98
+ SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
125
99
  FROM pg_class t
126
100
  INNER JOIN pg_index d ON t.oid = d.indrelid
127
101
  INNER JOIN pg_class i ON d.indexrelid = i.oid
128
102
  WHERE i.relkind = 'i'
129
- AND i.relname = '#{index_name}'
103
+ AND d.indisprimary = 'f'
130
104
  AND t.relname = '#{table_name}'
131
105
  AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
132
- SQL
106
+ ORDER BY i.relname
107
+ SQL
108
+
109
+
110
+ result.map do |row|
111
+ index_name = row[0]
112
+ unique = row[1] == true || row[1] == 't'
113
+ indkey = row[2].split(" ")
114
+ inddef = row[3]
115
+ oid = row[4]
116
+
117
+ columns = Hash[query(<<-SQL, "SCHEMA")]
118
+ SELECT a.attnum, a.attname
119
+ FROM pg_attribute a
120
+ WHERE a.attrelid = #{oid}
121
+ AND a.attnum IN (#{indkey.join(",")})
122
+ SQL
123
+
124
+ column_names = columns.stringify_keys.values_at(*indkey).compact
125
+
126
+ unless column_names.empty?
127
+ # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
128
+ desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
129
+ orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
130
+ where = inddef.scan(/WHERE (.+)$/).flatten[0]
131
+ using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
132
+
133
+ if ::Rails.version >= "5.2"
134
+ ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders, where: where, using: using)
135
+ else
136
+ ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
137
+ end
138
+ end
139
+ end.compact
140
+ end
141
+
142
+ def index_name_exists?(table_name, index_name, _default = nil)
143
+ exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
144
+ SELECT COUNT(*)
145
+ FROM pg_class t
146
+ INNER JOIN pg_index d ON t.oid = d.indrelid
147
+ INNER JOIN pg_class i ON d.indexrelid = i.oid
148
+ WHERE i.relkind = 'i'
149
+ AND i.relname = '#{index_name}'
150
+ AND t.relname = '#{table_name}'
151
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
152
+ SQL
153
+ end
154
+
155
+ def foreign_keys(table_name)
156
+ # mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
157
+ fk_info = select_all <<-SQL.strip_heredoc
158
+ 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
159
+ FROM pg_constraint c
160
+ JOIN pg_class t1 ON c.conrelid = t1.oid
161
+ JOIN pg_class t2 ON c.confrelid = t2.oid
162
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
163
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
164
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
165
+ WHERE c.contype = 'f'
166
+ AND t1.relname = #{quote(table_name)}
167
+ AND t3.nspname = '#{shard.name}'
168
+ ORDER BY c.conname
169
+ SQL
170
+
171
+ fk_info.map do |row|
172
+ options = {
173
+ column: row['column'],
174
+ name: row['name'],
175
+ primary_key: row['primary_key']
176
+ }
177
+
178
+ options[:on_delete] = extract_foreign_key_action(row['on_delete'])
179
+ options[:on_update] = extract_foreign_key_action(row['on_update'])
180
+
181
+ # strip the schema name from to_table if it matches
182
+ to_table = row['to_table']
183
+ to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
184
+ if to_table_qualified_name.schema == shard.name
185
+ to_table = to_table_qualified_name.identifier
186
+ end
187
+
188
+ ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
189
+ end
190
+ end
191
+ else
192
+ def foreign_keys(table_name)
193
+ super.each do |fk|
194
+ to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
195
+ if to_table_qualified_name.schema == shard.name
196
+ fk.to_table = to_table_qualified_name.identifier
197
+ end
198
+ end
199
+ end
133
200
  end
134
201
 
135
202
  def quote_local_table_name(name)
@@ -148,6 +215,10 @@ module Switchman
148
215
  name.quoted
149
216
  end
150
217
 
218
+ def with_global_table_name(&block)
219
+ with_local_table_name(false, &block)
220
+ end
221
+
151
222
  def with_local_table_name(enable = true)
152
223
  old_value = @use_local_table_name
153
224
  @use_local_table_name = enable
@@ -156,44 +227,6 @@ module Switchman
156
227
  @use_local_table_name = old_value
157
228
  end
158
229
 
159
- def foreign_keys(table_name)
160
-
161
- # mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
162
- fk_info = select_all <<-SQL.strip_heredoc
163
- 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
164
- FROM pg_constraint c
165
- JOIN pg_class t1 ON c.conrelid = t1.oid
166
- JOIN pg_class t2 ON c.confrelid = t2.oid
167
- JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
168
- JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
169
- JOIN pg_namespace t3 ON c.connamespace = t3.oid
170
- WHERE c.contype = 'f'
171
- AND t1.relname = #{quote(table_name)}
172
- AND t3.nspname = '#{shard.name}'
173
- ORDER BY c.conname
174
- SQL
175
-
176
- fk_info.map do |row|
177
- options = {
178
- column: row['column'],
179
- name: row['name'],
180
- primary_key: row['primary_key']
181
- }
182
-
183
- options[:on_delete] = extract_foreign_key_action(row['on_delete'])
184
- options[:on_update] = extract_foreign_key_action(row['on_update'])
185
-
186
- # strip the schema name from to_table if it matches
187
- to_table = row['to_table']
188
- to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
189
- if to_table_qualified_name.schema == shard.name
190
- to_table = to_table_qualified_name.identifier
191
- end
192
-
193
- ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
194
- end
195
- end
196
-
197
230
  def add_index_options(_table_name, _column_name, **)
198
231
  index_name, index_type, index_columns, index_options, algorithm, using = super
199
232
  algorithm = nil if DatabaseServer.creating_new_shard && algorithm == "CONCURRENTLY"
@@ -233,6 +233,10 @@ module Switchman
233
233
  connection.with_local_table_name { super }
234
234
  end
235
235
 
236
+ def table_name_matches?(from)
237
+ connection.with_global_table_name { super }
238
+ end
239
+
236
240
  # semi-private
237
241
  public
238
242
  def transpose_predicates(predicates,
@@ -250,7 +254,7 @@ module Switchman
250
254
  remove = true if type == :primary &&
251
255
  remove_nonlocal_primary_keys &&
252
256
  predicate.left.relation.model == klass &&
253
- predicate.is_a?(::Arel::Nodes::Equality)
257
+ (predicate.is_a?(::Arel::Nodes::Equality) || predicate.is_a?(::Arel::Nodes::In))
254
258
 
255
259
  current_source_shard =
256
260
  if source_shard
@@ -265,7 +269,7 @@ module Switchman
265
269
  new_right_value =
266
270
  case predicate.right
267
271
  when Array
268
- predicate.right.map {|val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove) }
272
+ predicate.right.map {|val| transpose_predicate_value(val, current_source_shard, target_shard, type, remove).presence }.compact
269
273
  else
270
274
  transpose_predicate_value(predicate.right, current_source_shard, target_shard, type, remove)
271
275
  end
@@ -340,7 +344,7 @@ module Switchman
340
344
  value
341
345
  else
342
346
  local_id = Shard.relative_id_for(current_id, current_shard, target_shard) || current_id
343
- local_id = [] if remove_non_local_ids && local_id.is_a?(Integer) && local_id > Shard::IDS_PER_SHARD
347
+ return nil if remove_non_local_ids && local_id.is_a?(Integer) && local_id > Shard::IDS_PER_SHARD
344
348
  if current_id != local_id
345
349
  # make a new bind param
346
350
  ::Arel::Nodes::BindParam.new(query_att.class.new(query_att.name, local_id, query_att.type))
@@ -106,10 +106,62 @@ module Switchman
106
106
  shards.first.activate(klass.shard_category) { yield(self, shards.first) }
107
107
  end
108
108
  else
109
- # TODO: implement local limit to avoid querying extra shards
110
- Shard.with_each_shard(shards, [klass.shard_category]) do
111
- shard(Shard.current(klass.shard_category), :to_a).activate(&block)
109
+ result_count = 0
110
+ can_order = false
111
+ result = Shard.with_each_shard(shards, [klass.shard_category]) do
112
+ # don't even query other shards if we're already past the limit
113
+ next if limit_value && result_count >= limit_value && order_values.empty?
114
+
115
+ relation = shard(Shard.current(klass.shard_category), :to_a)
116
+ # do a minimal query if possible
117
+ relation = relation.limit(limit_value - result_count) if limit_value && !result_count.zero? && order_values.empty?
118
+
119
+ shard_results = relation.activate(&block)
120
+
121
+ if shard_results.present?
122
+ can_order ||= can_order_cross_shard_results? unless order_values.empty?
123
+ raise OrderOnMultiShardQuery if !can_order && !order_values.empty? && result_count.positive?
124
+
125
+ result_count += shard_results.is_a?(Array) ? shard_results.length : 1
126
+ end
127
+ shard_results
128
+ end
129
+
130
+ result = reorder_cross_shard_results(result) if can_order
131
+ result.slice!(limit_value..-1) if limit_value
132
+ result
133
+ end
134
+ end
135
+
136
+ def can_order_cross_shard_results?
137
+ # we only presume to be able to post-sort the most basic of orderings
138
+ order_values.all? { |ov| ov.is_a?(::Arel::Nodes::Ordering) && ov.expr.is_a?(::Arel::Attributes::Attribute) }
139
+ end
140
+
141
+ def reorder_cross_shard_results(results)
142
+ results.sort! do |l, r|
143
+ result = 0
144
+ order_values.each do |ov|
145
+ if l.respond_to?(ov.expr.name)
146
+ a = l.send(ov.expr.name)
147
+ b = r.send(ov.expr.name)
148
+ else
149
+ a = l.attributes[ov.expr.name]
150
+ b = r.attributes[ov.expr.name]
151
+ end
152
+ next if a == b
153
+
154
+ if a.nil? || b.nil?
155
+ result = 1 if a.nil?
156
+ result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
157
+ else
158
+ result = a <=> b
159
+ end
160
+
161
+ result *= -1 if ov.is_a?(::Arel::Nodes::Descending)
162
+ break unless result.zero?
112
163
  end
164
+ result
113
165
  end
114
166
  end
115
167
  end
@@ -84,6 +84,10 @@ module Switchman
84
84
  @schema_cache
85
85
  end
86
86
 
87
+ def set_schema_cache(cache)
88
+ @schema_cache.copy_values(cache)
89
+ end
90
+
87
91
  %w{release_connection
88
92
  disconnect!
89
93
  flush!
@@ -5,14 +5,22 @@ module Switchman
5
5
  delegate :connection, to: :pool
6
6
  attr_reader :pool
7
7
 
8
+ SHARED_IVS = %i{@columns @columns_hash @primary_keys @data_sources @indexes}.freeze
9
+
8
10
  def initialize(pool)
9
11
  @pool = pool
10
12
  super(nil)
11
13
  end
12
14
 
13
15
  def copy_values(other_cache)
16
+ SHARED_IVS.each do |iv|
17
+ instance_variable_get(iv).replace(other_cache.instance_variable_get(iv))
18
+ end
19
+ end
20
+
21
+ def copy_references(other_cache)
14
22
  # use the same cached values but still fall back to the correct pool
15
- [:@columns, :@columns_hash, :@primary_keys, :@data_sources].each do |iv|
23
+ SHARED_IVS.each do |iv|
16
24
  instance_variable_set(iv, other_cache.instance_variable_get(iv))
17
25
  end
18
26
  end
@@ -8,7 +8,7 @@ module Switchman
8
8
  end
9
9
 
10
10
  def current_shard(category = :primary)
11
- @active_shards[category] || Shard.default
11
+ @active_shards&.[](category) || Shard.default
12
12
  end
13
13
  end
14
14
  end
@@ -24,7 +24,7 @@ module Switchman
24
24
  else
25
25
  server1 = Shard.default.database_server
26
26
  end
27
- server2 = DatabaseServer.create(Shard.default.database_server.config)
27
+ server2 = DatabaseServer.create(Shard.default.database_server.config.merge(server2: true))
28
28
 
29
29
  if server1 == Shard.default.database_server && server1.config[:shard1] && server1.config[:shard2]
30
30
  # look for the shards in the db already
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = "2.0.6"
4
+ VERSION = "2.0.11"
5
5
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: switchman
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.6
4
+ version: 2.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  - James Williams
9
9
  - Jacob Fugal
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-03-02 00:00:00.000000000 Z
13
+ date: 2021-06-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: railties
@@ -257,7 +257,7 @@ homepage: http://www.instructure.com/
257
257
  licenses:
258
258
  - MIT
259
259
  metadata: {}
260
- post_install_message:
260
+ post_install_message:
261
261
  rdoc_options: []
262
262
  require_paths:
263
263
  - lib
@@ -272,8 +272,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
272
  - !ruby/object:Gem::Version
273
273
  version: '0'
274
274
  requirements: []
275
- rubygems_version: 3.0.3
276
- signing_key:
275
+ rubygems_version: 3.2.15
276
+ signing_key:
277
277
  specification_version: 4
278
278
  summary: Rails sharding magic
279
279
  test_files: []