switchman 3.5.12 → 3.5.13

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: 9a18e4da75efcd07fcf8d46d08397d2323c7795f3f971a66561e03944383bf4e
4
- data.tar.gz: 65963d628b6a011a7e29d7b76735f6d6318afec42b3359e5cd4c6f4c21e591c6
3
+ metadata.gz: c0ab0712ea0711e482d32ddf5ce6ec740b399b6dc8074ea86eaaa092c13bbdd1
4
+ data.tar.gz: a3e43929c88727da33b2954966f7cf357bd2b8793eed33563f57908839e2d97d
5
5
  SHA512:
6
- metadata.gz: 278b27e999056a7b9a8bf1fbed3f4de12b110fc269410b7ffaf4c7fdcd340ef37e2af8174dd2ce499e90ab07483ee057261067224c474053707ab2de67c3c41c
7
- data.tar.gz: 5d9aa9b061b88fe2ea62d11005eaf4db9e05c9c65da11fd6d82bdaf5ddb707507bd024b95a2b9fca1ab3b194a158fbfc8ce66e5f6b5d5f9bf9327cd121d897ba
6
+ metadata.gz: 67a005a7e156773576077ade7723e1500d291e782cdfb4af9662cef6ba2a217b2e0743aaea8a5e8bffc1777295baf465f9d7678f6d8fa6c681215b1ad9c5817a
7
+ data.tar.gz: 7e72531b558a3fc0d447d63efeec37b5a0480ebe873ff2e76fb6334927aee10d5342a92b0be8336bd324da57c2df6ff154b5efb2d88b5cc0e9e7b16f60bc6c78
@@ -27,8 +27,10 @@ module Switchman
27
27
  quote_table_name(name)
28
28
  end
29
29
 
30
- def schema_migration
31
- ::ActiveRecord::SchemaMigration
30
+ if ::Rails.version < "7.1"
31
+ def schema_migration
32
+ ::ActiveRecord::SchemaMigration
33
+ end
32
34
  end
33
35
 
34
36
  protected
@@ -298,11 +298,48 @@ module Switchman
298
298
  record.has_attribute?(reflection.foreign_key) && record.send(reflection.foreign_key) != key
299
299
  end
300
300
 
301
- def save_belongs_to_association(reflection)
302
- # this seems counter-intuitive, but the autosave code will assign to attribute bypassing switchman,
303
- # after reading the id attribute _without_ bypassing switchman. So we need Shard.current for the
304
- # category of the associated record to match Shard.current for the category of self
305
- shard.activate(connection_class_for_self_for_reflection(reflection)) { super }
301
+ if ::Rails.version < "7.1"
302
+ def save_belongs_to_association(reflection)
303
+ # this seems counter-intuitive, but the autosave code will assign to attribute bypassing switchman,
304
+ # after reading the id attribute _without_ bypassing switchman. So we need Shard.current for the
305
+ # category of the associated record to match Shard.current for the category of self
306
+ shard.activate(connection_class_for_self_for_reflection(reflection)) { super }
307
+ end
308
+ else
309
+ def save_belongs_to_association(reflection)
310
+ association = association_instance_get(reflection.name)
311
+ return unless association&.loaded? && !association.stale_target?
312
+
313
+ record = association.load_target
314
+ return unless record && !record.destroyed?
315
+
316
+ autosave = reflection.options[:autosave]
317
+
318
+ if autosave && record.marked_for_destruction?
319
+ foreign_key = Array(reflection.foreign_key)
320
+ foreign_key.each { |key| self[key] = nil }
321
+ record.destroy
322
+ elsif autosave != false
323
+ if record.new_record? || (autosave && record.changed_for_autosave?)
324
+ saved = record.save(validate: !autosave)
325
+ end
326
+
327
+ if association.updated?
328
+ primary_key = Array(compute_primary_key(reflection, record)).map(&:to_s)
329
+ foreign_key = Array(reflection.foreign_key)
330
+
331
+ primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
332
+ primary_key_foreign_key_pairs.each do |pk, fk|
333
+ # Notable change: add relative_id_for here
334
+ association_id = Shard.relative_id_for(record._read_attribute(pk), record.shard, shard)
335
+ self[fk] = association_id unless self[fk] == association_id
336
+ end
337
+ association.loaded!
338
+ end
339
+
340
+ saved if autosave
341
+ end
342
+ end
306
343
  end
307
344
  end
308
345
  end
@@ -57,7 +57,7 @@ module Switchman
57
57
  end
58
58
 
59
59
  def clear_query_caches_for_current_thread
60
- ::ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
60
+ ::ActiveRecord::Base.connection_handler.connection_pool_list(:all).each do |pool|
61
61
  pool.connection(switch_shard: false).clear_query_cache if pool.active_connection?
62
62
  end
63
63
  end
@@ -265,9 +265,9 @@ module Switchman
265
265
  result
266
266
  end
267
267
 
268
- def transaction(**kwargs, &block)
268
+ def transaction(...)
269
269
  shard.activate(self.class.connection_class_for_self) do
270
- self.class.transaction(**kwargs, &block)
270
+ self.class.transaction(...)
271
271
  end
272
272
  end
273
273
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Switchman
4
+ module ActiveRecord
5
+ module ConnectionHandler
6
+ def resolve_pool_config(config, connection_name, role, shard)
7
+ ret = super
8
+ # Make *all* pool configs use the same schema reflection
9
+ ret.schema_reflection = ConnectionHandler.global_schema_reflection
10
+ ret
11
+ end
12
+
13
+ def self.global_schema_reflection
14
+ @global_schema_reflection ||= ::ActiveRecord::ConnectionAdapters::SchemaReflection.new(nil)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,22 +3,24 @@
3
3
  module Switchman
4
4
  module ActiveRecord
5
5
  module ConnectionPool
6
- def get_schema_cache(connection)
7
- self.schema_cache ||= SharedSchemaCache.get_schema_cache(connection)
8
- self.schema_cache.connection = connection
6
+ if ::Rails.version < "7.1"
7
+ def get_schema_cache(connection)
8
+ self.schema_cache ||= SharedSchemaCache.get_schema_cache(connection)
9
+ self.schema_cache.connection = connection
9
10
 
10
- self.schema_cache
11
- end
11
+ self.schema_cache
12
+ end
12
13
 
13
- # rubocop:disable Naming/AccessorMethodName override method
14
- def set_schema_cache(cache)
15
- schema_cache = get_schema_cache(cache.connection)
14
+ # rubocop:disable Naming/AccessorMethodName override method
15
+ def set_schema_cache(cache)
16
+ schema_cache = get_schema_cache(cache.connection)
16
17
 
17
- cache.instance_variables.each do |x|
18
- schema_cache.instance_variable_set(x, cache.instance_variable_get(x))
18
+ cache.instance_variables.each do |x|
19
+ schema_cache.instance_variable_set(x, cache.instance_variable_get(x))
20
+ end
19
21
  end
22
+ # rubocop:enable Naming/AccessorMethodName override method
20
23
  end
21
- # rubocop:enable Naming/AccessorMethodName override method
22
24
 
23
25
  def default_schema
24
26
  connection unless @schemas
@@ -7,14 +7,26 @@ module Switchman
7
7
  # since all should point to the same data, even if multiple are writable
8
8
  # (Picks 'primary' since it is guaranteed to exist and switchman handles activating
9
9
  # deploy through other means)
10
- def configs_for(include_replicas: false, name: nil, **)
11
- res = super
12
- if name && !include_replicas
13
- return nil unless name.end_with?("primary")
14
- elsif !include_replicas
15
- return res.select { |config| config.name.end_with?("primary") }
10
+ if ::Rails.version < "7.1"
11
+ def configs_for(include_replicas: false, name: nil, **)
12
+ res = super
13
+ if name && !include_replicas
14
+ return nil unless name.end_with?("primary")
15
+ elsif !include_replicas
16
+ return res.select { |config| config.name.end_with?("primary") }
17
+ end
18
+ res
19
+ end
20
+ else
21
+ def configs_for(include_hidden: false, name: nil, **)
22
+ res = super
23
+ if name && !include_hidden
24
+ return nil unless name.end_with?("primary")
25
+ elsif !include_hidden
26
+ return res.select { |config| config.name.end_with?("primary") }
27
+ end
28
+ res
16
29
  end
17
- res
18
30
  end
19
31
 
20
32
  private
@@ -42,26 +42,56 @@ module Switchman
42
42
  primary_shard.activate { super }
43
43
  end
44
44
 
45
- def exists?(conditions = :none)
46
- conditions = conditions.id if ::ActiveRecord::Base === conditions
47
- return false unless conditions
45
+ if ::Rails.version < "7.1"
46
+ def exists?(conditions = :none)
47
+ conditions = conditions.id if ::ActiveRecord::Base === conditions
48
+ return false unless conditions
48
49
 
49
- relation = apply_join_dependency(eager_loading: false)
50
- return false if ::ActiveRecord::NullRelation === relation
50
+ relation = apply_join_dependency(eager_loading: false)
51
+ return false if ::ActiveRecord::NullRelation === relation
51
52
 
52
- relation = relation.except(:select, :order).select("1 AS one").limit(1)
53
+ relation = relation.except(:select, :order).select("1 AS one").limit(1)
53
54
 
54
- case conditions
55
- when Array, Hash
56
- relation = relation.where(conditions)
57
- else
58
- relation = relation.where(table[primary_key].eq(conditions)) if conditions != :none
55
+ case conditions
56
+ when Array, Hash
57
+ relation = relation.where(conditions)
58
+ else
59
+ relation = relation.where(table[primary_key].eq(conditions)) if conditions != :none
60
+ end
61
+
62
+ relation.activate do |shard_rel|
63
+ return true if connection.select_value(shard_rel.arel, "#{name} Exists")
64
+ end
65
+ false
59
66
  end
67
+ else
68
+ def exists?(conditions = :none)
69
+ return false if @none
70
+
71
+ if Base === conditions
72
+ raise ArgumentError, <<-TEXT.squish
73
+ You are passing an instance of ActiveRecord::Base to `exists?`.
74
+ Please pass the id of the object by calling `.id`.
75
+ TEXT
76
+ end
60
77
 
61
- relation.activate do |shard_rel|
62
- return true if connection.select_value(shard_rel.arel, "#{name} Exists")
78
+ return false if !conditions || limit_value == 0 # rubocop:disable Style/NumericPredicate
79
+
80
+ if eager_loading?
81
+ relation = apply_join_dependency(eager_loading: false)
82
+ return relation.exists?(conditions)
83
+ end
84
+
85
+ relation = construct_relation_for_exists(conditions)
86
+ return false if relation.where_clause.contradiction?
87
+
88
+ relation.activate do |shard_rel|
89
+ return true if skip_query_cache_if_necessary do
90
+ connection.select_rows(shard_rel.arel, "#{name} Exists?").size == 1
91
+ end
92
+ end
93
+ false
63
94
  end
64
- false
65
95
  end
66
96
  end
67
97
  end
@@ -5,8 +5,10 @@ module Switchman
5
5
  module LogSubscriber
6
6
  # sadly, have to completely replace this
7
7
  def sql(event)
8
- self.class.runtime += event.duration
9
- return unless logger.debug?
8
+ if ::Rails.version < "7.1"
9
+ self.class.runtime += event.duration
10
+ return unless logger.debug?
11
+ end
10
12
 
11
13
  payload = event.payload
12
14
 
@@ -27,7 +29,11 @@ module Switchman
27
29
  end
28
30
 
29
31
  name = colorize_payload_name(name, payload[:name])
30
- sql = color(sql, sql_color(sql), true)
32
+ sql = if ::Rails.version < "7.1"
33
+ color(sql, sql_color(sql), true)
34
+ else
35
+ color(sql, sql_color(sql), bold: true)
36
+ end
31
37
 
32
38
  debug " #{name} #{sql}#{binds}#{shard}"
33
39
  end
@@ -29,7 +29,11 @@ module Switchman
29
29
  db_name_hash = Zlib.crc32(Shard.current.name)
30
30
  shard_name_hash = ::ActiveRecord::Migrator::MIGRATOR_SALT * db_name_hash
31
31
  # Store in internalmetadata to allow other tools to be able to lock out migrations
32
- ::ActiveRecord::InternalMetadata[:migrator_advisory_lock_id] = shard_name_hash
32
+ if ::Rails.version < "7.1"
33
+ ::ActiveRecord::InternalMetadata[:migrator_advisory_lock_id] = shard_name_hash
34
+ else
35
+ ::ActiveRecord::InternalMetadata.new(connection)[:migrator_advisory_lock_id] = shard_name_hash
36
+ end
33
37
  shard_name_hash
34
38
  end
35
39
 
@@ -48,17 +52,30 @@ module Switchman
48
52
  module MigrationContext
49
53
  def migrate(...)
50
54
  connection = ::ActiveRecord::Base.connection
51
- connection_pool = ::ActiveRecord::Base.connection_pool
52
- previous_schema_cache = connection_pool.get_schema_cache(connection)
53
- temporary_schema_cache = ::ActiveRecord::ConnectionAdapters::SchemaCache.new(connection)
55
+ schema_cache_holder = ::ActiveRecord::Base.connection_pool
56
+ schema_cache_holder = schema_cache_holder.schema_reflection if ::Rails.version >= "7.1"
57
+ previous_schema_cache = if ::Rails.version < "7.1"
58
+ schema_cache_holder.get_schema_cache(connection)
59
+ else
60
+ schema_cache_holder.instance_variable_get(:@cache)
61
+ end
62
+
63
+ if ::Rails.version < "7.1"
64
+ temporary_schema_cache = ::ActiveRecord::ConnectionAdapters::SchemaCache.new(connection)
65
+
66
+ reset_column_information
67
+ schema_cache_holder.set_schema_cache(temporary_schema_cache)
68
+ else
69
+ schema_cache_holder.instance_variable_get(:@cache)
54
70
 
55
- reset_column_information
56
- connection_pool.set_schema_cache(temporary_schema_cache)
71
+ reset_column_information
72
+ schema_cache_holder.clear!
73
+ end
57
74
 
58
75
  begin
59
76
  super(...)
60
77
  ensure
61
- connection_pool.set_schema_cache(previous_schema_cache)
78
+ schema_cache_holder.set_schema_cache(previous_schema_cache)
62
79
  reset_column_information
63
80
  end
64
81
  end
@@ -5,28 +5,57 @@ module Switchman
5
5
  module QueryCache
6
6
  private
7
7
 
8
- def cache_sql(sql, name, binds)
9
- # have to include the shard id in the cache key because of switching dbs on the same connection
10
- sql = "#{shard.id}::#{sql}"
11
- @lock.synchronize do
12
- result =
13
- if query_cache[sql].key?(binds)
14
- args = {
15
- sql: sql,
16
- binds: binds,
17
- name: name,
18
- connection_id: object_id,
19
- cached: true,
20
- type_casted_binds: -> { type_casted_binds(binds) }
21
- }
22
- ::ActiveSupport::Notifications.instrument(
23
- "sql.active_record",
24
- args
25
- )
26
- query_cache[sql][binds]
8
+ if ::Rails.version < "7.1"
9
+ def cache_sql(sql, name, binds)
10
+ # have to include the shard id in the cache key because of switching dbs on the same connection
11
+ sql = "#{shard.id}::#{sql}"
12
+ @lock.synchronize do
13
+ result =
14
+ if query_cache[sql].key?(binds)
15
+ args = {
16
+ sql: sql,
17
+ binds: binds,
18
+ name: name,
19
+ connection_id: object_id,
20
+ cached: true,
21
+ type_casted_binds: -> { type_casted_binds(binds) }
22
+ }
23
+ ::ActiveSupport::Notifications.instrument(
24
+ "sql.active_record",
25
+ args
26
+ )
27
+ query_cache[sql][binds]
28
+ else
29
+ query_cache[sql][binds] = yield
30
+ end
31
+ result.dup
32
+ end
33
+ end
34
+ else
35
+ def cache_sql(sql, name, binds)
36
+ # have to include the shard id in the cache key because of switching dbs on the same connection
37
+ sql = "#{shard.id}::#{sql}"
38
+ key = binds.empty? ? sql : [sql, binds]
39
+ result = nil
40
+ hit = false
41
+
42
+ @lock.synchronize do
43
+ if (result = @query_cache.delete(key))
44
+ hit = true
45
+ @query_cache[key] = result
27
46
  else
28
- query_cache[sql][binds] = yield
47
+ result = @query_cache[key] = yield
48
+ @query_cache.shift if @query_cache_max_size && @query_cache.size > @query_cache_max_size
29
49
  end
50
+ end
51
+
52
+ if hit
53
+ ::ActiveSupport::Notifications.instrument(
54
+ "sql.active_record",
55
+ cache_notification_info(sql, name, binds)
56
+ )
57
+ end
58
+
30
59
  result.dup
31
60
  end
32
61
  end
@@ -175,7 +175,7 @@ module Switchman
175
175
  end
176
176
 
177
177
  def sharded_foreign_key?(relation, column)
178
- models_for_table(relation.table_name).any? { |m| m.sharded_column?(column) }
178
+ models_for_table(relation.name).any? { |m| m.sharded_column?(column) }
179
179
  end
180
180
 
181
181
  def sharded_primary_key?(relation, column)
@@ -187,7 +187,7 @@ module Switchman
187
187
 
188
188
  def source_shard_for_foreign_key(relation, column)
189
189
  reflection = nil
190
- models_for_table(relation.table_name).each do |model|
190
+ models_for_table(relation.name).each do |model|
191
191
  reflection = model.send(:reflection_for_integer_attribute, column)
192
192
  break if reflection
193
193
  end
@@ -14,21 +14,28 @@ module Switchman
14
14
  # Code adapted from the code in rails proper
15
15
  @connection_subscriber =
16
16
  ::ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
17
- spec_name = payload[:spec_name] if payload.key?(:spec_name)
17
+ spec_name = if ::Rails.version < "7.1"
18
+ payload[:spec_name] if payload.key?(:spec_name)
19
+ elsif payload.key?(:connection_name)
20
+ payload[:connection_name]
21
+ end
18
22
  shard = payload[:shard] if payload.key?(:shard)
19
- setup_shared_connection_pool
20
23
 
21
24
  if spec_name && !FORBIDDEN_DB_ENVS.include?(shard)
22
25
  begin
23
26
  connection = ::ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
27
+ connection.connect! if ::Rails.version >= "7.1" # eagerly validate the connection
24
28
  rescue ::ActiveRecord::ConnectionNotEstablished, ::ActiveRecord::NoDatabaseError
25
29
  connection = nil
26
30
  end
27
31
 
28
- if connection && !@fixture_connections.include?(connection)
29
- connection.begin_transaction joinable: false, _lazy: false
30
- connection.pool.lock_thread = true if lock_threads
31
- @fixture_connections << connection
32
+ if connection
33
+ setup_shared_connection_pool
34
+ unless @fixture_connections.include?(connection)
35
+ connection.begin_transaction joinable: false, _lazy: false
36
+ connection.pool.lock_thread = true if lock_threads
37
+ @fixture_connections << connection
38
+ end
32
39
  end
33
40
  end
34
41
  end
@@ -37,7 +44,7 @@ module Switchman
37
44
  def enlist_fixture_connections
38
45
  setup_shared_connection_pool
39
46
 
40
- ::ActiveRecord::Base.connection_handler.connection_pool_list.reject do |cp|
47
+ ::ActiveRecord::Base.connection_handler.connection_pool_list(:primary).reject do |cp|
41
48
  FORBIDDEN_DB_ENVS.include?(cp.db_config.env_name.to_sym)
42
49
  end.map(&:connection)
43
50
  end
@@ -24,27 +24,29 @@ module Switchman
24
24
  collector << quote_local_table_name(join_name) << "." << quote_column_name(o.name)
25
25
  end
26
26
 
27
- def visit_Arel_Nodes_HomogeneousIn(o, collector)
28
- collector.preparable = false
27
+ if ::Rails.version < "7.1"
28
+ def visit_Arel_Nodes_HomogeneousIn(o, collector)
29
+ collector.preparable = false
29
30
 
30
- collector << quote_local_table_name(o.table_name) << "." << quote_column_name(o.column_name)
31
+ collector << quote_local_table_name(o.table_name) << "." << quote_column_name(o.column_name)
31
32
 
32
- collector << if o.type == :in
33
- " IN ("
34
- else
35
- " NOT IN ("
36
- end
33
+ collector << if o.type == :in
34
+ " IN ("
35
+ else
36
+ " NOT IN ("
37
+ end
37
38
 
38
- values = o.casted_values
39
+ values = o.casted_values
39
40
 
40
- if values.empty?
41
- collector << @connection.quote(nil)
42
- else
43
- collector.add_binds(values, o.proc_for_binds, &bind_block)
44
- end
41
+ if values.empty?
42
+ collector << @connection.quote(nil)
43
+ else
44
+ collector.add_binds(values, o.proc_for_binds, &bind_block)
45
+ end
45
46
 
46
- collector << ")"
47
- collector
47
+ collector << ")"
48
+ collector
49
+ end
48
50
  end
49
51
 
50
52
  # rubocop:enable Naming/MethodName
@@ -228,7 +228,11 @@ module Switchman
228
228
  unless schema == false
229
229
  shard.activate do
230
230
  ::ActiveRecord::Base.connection.transaction(requires_new: true) do
231
- ::ActiveRecord::Base.connection.migration_context.migrate
231
+ if ::Rails.version < "7.1"
232
+ ::ActiveRecord::Base.connection.migration_context.migrate
233
+ else
234
+ ::ActiveRecord::MigrationContext.new(::ActiveRecord::Migrator.migrations_paths).migrate
235
+ end
232
236
  end
233
237
 
234
238
  ::ActiveRecord::Base.descendants.reject do |m|
@@ -5,7 +5,7 @@ module Switchman
5
5
  isolate_namespace Switchman
6
6
 
7
7
  # enable Rails 6.1 style connection handling
8
- config.active_record.legacy_connection_handling = false
8
+ config.active_record.legacy_connection_handling = false if ::Rails.version < "7.1"
9
9
  config.active_record.writing_role = :primary
10
10
 
11
11
  ::GuardRail.singleton_class.prepend(GuardRail::ClassMethods)
@@ -60,6 +60,9 @@ module Switchman
60
60
  )
61
61
  end
62
62
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::AbstractAdapter)
63
+ unless ::Rails.version < "7.1"
64
+ ::ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ActiveRecord::ConnectionHandler)
65
+ end
63
66
  ::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecord::ConnectionPool)
64
67
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::QueryCache)
65
68
  ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(ActiveRecord::PostgreSQLAdapter)
@@ -166,7 +166,11 @@ module Switchman
166
166
  # clear connections prior to forking (no more queries will be executed in the parent,
167
167
  # and we want them gone so that we don't accidentally use them post-fork doing something
168
168
  # silly like dealloc'ing prepared statements)
169
- ::ActiveRecord::Base.clear_all_connections!
169
+ if ::Rails.version < "7.1"
170
+ ::ActiveRecord::Base.clear_all_connections!(nil)
171
+ else
172
+ ::ActiveRecord::Base.connection_handler.clear_all_connections!(:all)
173
+ end
170
174
 
171
175
  parent_process_name = sanitized_process_title
172
176
  ret = ::Parallel.map(scopes, in_processes: (scopes.length > 1) ? parallel : 0) do |server, subscope|
@@ -258,7 +262,7 @@ module Switchman
258
262
  else
259
263
  shard = partition_object.shard
260
264
  end
261
- when Integer, /^\d+$/, /^(\d+)~(\d+)$/
265
+ when Integer, /\A\d+\Z/, /\A(\d+)~(\d+)\Z/
262
266
  local_id, shard = Shard.local_id_for(partition_object)
263
267
  local_id ||= partition_object
264
268
  object = local_id unless partition_proc
@@ -300,14 +304,14 @@ module Switchman
300
304
  case any_id
301
305
  when ::ActiveRecord::Base
302
306
  any_id.id
303
- when /^(\d+)~(-?\d+)$/
307
+ when /\A(\d+)~(-?\d+)\Z/
304
308
  local_id = $2.to_i
305
309
  signed_id_operation(local_id) do |id|
306
310
  return nil if id > IDS_PER_SHARD
307
311
 
308
312
  ($1.to_i * IDS_PER_SHARD) + id
309
313
  end
310
- when Integer, /^-?\d+$/
314
+ when Integer, /\A-?\d+\Z/
311
315
  any_id.to_i
312
316
  end
313
317
  end
@@ -410,7 +414,10 @@ module Switchman
410
414
  end
411
415
  end
412
416
 
417
+ # this resets the default shard on rails 7.1+, but we want to preserve it
418
+ shard_was = klass.default_shard
413
419
  klass.connects_to shards: connects_to_hash
420
+ klass.default_shard = shard_was
414
421
  end
415
422
  end
416
423
 
@@ -519,6 +526,10 @@ module Switchman
519
526
  id
520
527
  end
521
528
 
529
+ def original_id_value
530
+ id
531
+ end
532
+
522
533
  def activate(*classes, &block)
523
534
  shards = hashify_classes(classes)
524
535
  Shard.activate(shards, &block)
@@ -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.merge(server2: true))
22
+ server2 = DatabaseServer.create(Shard.default.database_server.config.merge(server2: true, schema_dump: false))
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = "3.5.12"
4
+ VERSION = "3.5.13"
5
5
  end
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.5.12
4
+ version: 3.5.13
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: 2023-10-03 00:00:00.000000000 Z
13
+ date: 2023-10-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 6.1.4
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '7.1'
24
+ version: '7.2'
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
@@ -31,7 +31,7 @@ dependencies:
31
31
  version: 6.1.4
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '7.1'
34
+ version: '7.2'
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: guardrail
37
37
  requirement: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  version: '6.1'
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: '7.1'
72
+ version: '7.2'
73
73
  type: :runtime
74
74
  prerelease: false
75
75
  version_requirements: !ruby/object:Gem::Requirement
@@ -79,21 +79,21 @@ dependencies:
79
79
  version: '6.1'
80
80
  - - "<"
81
81
  - !ruby/object:Gem::Version
82
- version: '7.1'
82
+ version: '7.2'
83
83
  - !ruby/object:Gem::Dependency
84
- name: byebug
84
+ name: debug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1.8'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1.8'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pg
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -108,20 +108,6 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.2'
111
- - !ruby/object:Gem::Dependency
112
- name: pry
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rake
127
113
  requirement: !ruby/object:Gem::Requirement
@@ -255,6 +241,7 @@ files:
255
241
  - lib/switchman/active_record/attribute_methods.rb
256
242
  - lib/switchman/active_record/base.rb
257
243
  - lib/switchman/active_record/calculations.rb
244
+ - lib/switchman/active_record/connection_handler.rb
258
245
  - lib/switchman/active_record/connection_pool.rb
259
246
  - lib/switchman/active_record/database_configurations.rb
260
247
  - lib/switchman/active_record/database_configurations/database_config.rb