switchman 3.4.2 → 3.5.1

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +15 -14
  3. data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
  4. data/db/migrate/20190114212900_add_unique_name_indexes.rb +10 -4
  5. data/lib/switchman/active_record/associations.rb +16 -5
  6. data/lib/switchman/active_record/attribute_methods.rb +67 -22
  7. data/lib/switchman/active_record/base.rb +32 -12
  8. data/lib/switchman/active_record/calculations.rb +37 -33
  9. data/lib/switchman/active_record/connection_pool.rb +4 -2
  10. data/lib/switchman/active_record/database_configurations.rb +12 -7
  11. data/lib/switchman/active_record/finder_methods.rb +1 -1
  12. data/lib/switchman/active_record/log_subscriber.rb +2 -2
  13. data/lib/switchman/active_record/migration.rb +4 -2
  14. data/lib/switchman/active_record/persistence.rb +18 -0
  15. data/lib/switchman/active_record/postgresql_adapter.rb +11 -10
  16. data/lib/switchman/active_record/query_cache.rb +1 -1
  17. data/lib/switchman/active_record/query_methods.rb +72 -26
  18. data/lib/switchman/active_record/relation.rb +13 -7
  19. data/lib/switchman/active_record/spawn_methods.rb +2 -2
  20. data/lib/switchman/active_record/statement_cache.rb +2 -2
  21. data/lib/switchman/active_record/tasks/database_tasks.rb +1 -1
  22. data/lib/switchman/active_record/test_fixtures.rb +19 -16
  23. data/lib/switchman/active_support/cache.rb +4 -1
  24. data/lib/switchman/arel.rb +6 -6
  25. data/lib/switchman/call_super.rb +1 -1
  26. data/lib/switchman/database_server.rb +20 -16
  27. data/lib/switchman/default_shard.rb +3 -3
  28. data/lib/switchman/engine.rb +33 -18
  29. data/lib/switchman/environment.rb +2 -2
  30. data/lib/switchman/errors.rb +4 -1
  31. data/lib/switchman/guard_rail/relation.rb +1 -1
  32. data/lib/switchman/parallel.rb +1 -1
  33. data/lib/switchman/r_spec_helper.rb +10 -10
  34. data/lib/switchman/shard.rb +30 -23
  35. data/lib/switchman/sharded_instrumenter.rb +5 -1
  36. data/lib/switchman/test_helper.rb +1 -1
  37. data/lib/switchman/version.rb +1 -1
  38. data/lib/switchman.rb +12 -4
  39. data/lib/tasks/switchman.rake +40 -37
  40. metadata +9 -9
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'securerandom'
3
+ require "securerandom"
4
4
 
5
5
  module Switchman
6
6
  class DatabaseServer
@@ -16,13 +16,13 @@ module Switchman
16
16
 
17
17
  def find(id_or_all)
18
18
  return all if id_or_all == :all
19
- return id_or_all.map { |id| database_servers[id || ::Rails.env] }.compact.uniq if id_or_all.is_a?(Array)
19
+ return id_or_all.filter_map { |id| database_servers[id || ::Rails.env] }.uniq if id_or_all.is_a?(Array)
20
20
 
21
21
  database_servers[id_or_all || ::Rails.env]
22
22
  end
23
23
 
24
24
  def create(settings = {})
25
- raise 'database servers should be set up in database.yml' unless ::Rails.env.test?
25
+ raise "database servers should be set up in database.yml" unless ::Rails.env.test?
26
26
 
27
27
  id = settings[:id]
28
28
  unless id
@@ -64,8 +64,8 @@ module Switchman
64
64
  @database_servers = {}.with_indifferent_access
65
65
  roles = []
66
66
  ::ActiveRecord::Base.configurations.configurations.each do |config|
67
- if config.name.include?('/')
68
- name, role = config.name.split('/')
67
+ if config.name.include?("/")
68
+ name, role = config.name.split("/")
69
69
  else
70
70
  name, role = config.env_name, config.name
71
71
  end
@@ -110,8 +110,9 @@ module Switchman
110
110
  self.class.send(:database_servers).delete(id) if id
111
111
  Shard.sharded_models.each do |klass|
112
112
  self.class.all_roles.each do |role|
113
- klass.connection_handler.remove_connection_pool(klass.connection_specification_name, role: role,
114
- shard: id.to_sym)
113
+ klass.connection_handler.remove_connection_pool(klass.connection_specification_name,
114
+ role: role,
115
+ shard: id.to_sym)
115
116
  end
116
117
  end
117
118
  end
@@ -142,11 +143,13 @@ module Switchman
142
143
  # value of GuardRail.environment)
143
144
  def guard!(environment = :secondary)
144
145
  DatabaseServer.send(:reference_role, environment)
145
- ::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => environment }, klasses: [::ActiveRecord::Base] }
146
+ ::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => environment },
147
+ klasses: [::ActiveRecord::Base] }
146
148
  end
147
149
 
148
150
  def unguard!
149
- ::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => :_switchman_inherit }, klasses: [::ActiveRecord::Base] }
151
+ ::ActiveRecord::Base.connected_to_stack << { shard_roles: { id.to_sym => :_switchman_inherit },
152
+ klasses: [::ActiveRecord::Base] }
150
153
  end
151
154
 
152
155
  def unguard
@@ -162,7 +165,7 @@ module Switchman
162
165
 
163
166
  def shards
164
167
  if id == ::Rails.env
165
- Shard.where('database_server_id IS NULL OR database_server_id=?', id)
168
+ Shard.where("database_server_id IS NULL OR database_server_id=?", id)
166
169
  else
167
170
  Shard.where(database_server_id: id)
168
171
  end
@@ -187,7 +190,7 @@ module Switchman
187
190
  end
188
191
 
189
192
  id ||= begin
190
- id_seq = Shard.connection.quote(Shard.connection.quote_table_name('switchman_shards_id_seq'))
193
+ id_seq = Shard.connection.quote(Shard.connection.quote_table_name("switchman_shards_id_seq"))
191
194
  next_id = Shard.connection.select_value("SELECT nextval(#{id_seq})")
192
195
  next_id.to_i
193
196
  end
@@ -204,17 +207,18 @@ module Switchman
204
207
  name: name,
205
208
  database_server_id: self.id)
206
209
  if create_statement
207
- if ::ActiveRecord::Base.connection.select_value("SELECT 1 FROM pg_namespace WHERE nspname=#{::ActiveRecord::Base.connection.quote(name)}")
210
+ if ::ActiveRecord::Base.connection.select_value(
211
+ "SELECT 1 FROM pg_namespace WHERE nspname=#{::ActiveRecord::Base.connection.quote(name)}"
212
+ )
208
213
  schema_already_existed = true
209
- raise 'This schema already exists; cannot overwrite'
214
+ raise "This schema already exists; cannot overwrite"
210
215
  end
211
216
  Array(create_statement.call).each do |stmt|
212
217
  ::ActiveRecord::Base.connection.execute(stmt)
213
218
  end
214
219
  end
215
- if config[:adapter] == 'postgresql'
216
- old_proc = ::ActiveRecord::Base.connection.raw_connection.set_notice_processor do
217
- end
220
+ if config[:adapter] == "postgresql"
221
+ old_proc = ::ActiveRecord::Base.connection.raw_connection.set_notice_processor {}
218
222
  end
219
223
  old_verbose = ::ActiveRecord::Migration.verbose
220
224
  ::ActiveRecord::Migration.verbose = false
@@ -3,9 +3,9 @@
3
3
  module Switchman
4
4
  class DefaultShard
5
5
  def id
6
- 'default'
6
+ "default"
7
7
  end
8
- alias cache_key id
8
+ alias_method :cache_key, :id
9
9
  def activate(*_classes)
10
10
  yield
11
11
  end
@@ -58,7 +58,7 @@ module Switchman
58
58
  end
59
59
 
60
60
  def _dump(_depth)
61
- ''
61
+ ""
62
62
  end
63
63
 
64
64
  def self._load(_str)
@@ -10,19 +10,23 @@ module Switchman
10
10
 
11
11
  ::GuardRail.singleton_class.prepend(GuardRail::ClassMethods)
12
12
 
13
- # after :initialize_dependency_mechanism to ensure autoloading is configured for any downstream initializers that care
14
- # In rails 7.0 we should be able to just use an explicit after on configuring the once autoloaders and not need to go monkey around with initializer order
15
- if ::Rails.version < '7.0'
16
- initialize_dependency_mechanism = ::Rails::Application::Bootstrap.initializers.find { |i| i.name == :initialize_dependency_mechanism }
13
+ # after :initialize_dependency_mechanism to ensure autoloading is
14
+ # configured for any downstream initializers that care. In rails 7.0 we
15
+ # should be able to just use an explicit after on configuring the once
16
+ # autoloaders and not need to go monkey around with initializer order
17
+ if ::Rails.version < "7.0"
18
+ initialize_dependency_mechanism = ::Rails::Application::Bootstrap.initializers.find do |i|
19
+ i.name == :initialize_dependency_mechanism
20
+ end
17
21
  initialize_dependency_mechanism.instance_variable_get(:@options)[:after] = :set_autoload_paths
18
22
  end
19
23
 
20
- initializer 'switchman.active_record_patch',
21
- before: 'active_record.initialize_database',
22
- after: (::Rails.version < '7.0' ? :initialize_dependency_mechanism : :setup_once_autoloader) do
24
+ initializer "switchman.active_record_patch",
25
+ before: "active_record.initialize_database",
26
+ after: ((::Rails.version < "7.0") ? :initialize_dependency_mechanism : :setup_once_autoloader) do
23
27
  ::ActiveSupport.on_load(:active_record) do
24
28
  # Switchman requires postgres, so just always load the pg adapter
25
- require 'active_record/connection_adapters/postgresql_adapter'
29
+ require "active_record/connection_adapters/postgresql_adapter"
26
30
 
27
31
  self.default_shard = ::Rails.env.to_sym
28
32
  self.default_role = :primary
@@ -50,14 +54,20 @@ module Switchman
50
54
  ::ActiveRecord::Associations::CollectionProxy.include(ActiveRecord::Associations::CollectionProxy)
51
55
 
52
56
  ::ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecord::Associations::Preloader::Association)
53
- ::ActiveRecord::Associations::Preloader::Association::LoaderRecords.prepend(ActiveRecord::Associations::Preloader::Association::LoaderRecords) unless ::Rails.version < '7.0'
57
+ unless ::Rails.version < "7.0"
58
+ ::ActiveRecord::Associations::Preloader::Association::LoaderRecords.prepend(
59
+ ActiveRecord::Associations::Preloader::Association::LoaderRecords
60
+ )
61
+ end
54
62
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::AbstractAdapter)
55
63
  ::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecord::ConnectionPool)
56
64
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::QueryCache)
57
65
  ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(ActiveRecord::PostgreSQLAdapter)
58
66
 
59
67
  ::ActiveRecord::DatabaseConfigurations.prepend(ActiveRecord::DatabaseConfigurations)
60
- ::ActiveRecord::DatabaseConfigurations::DatabaseConfig.prepend(ActiveRecord::DatabaseConfigurations::DatabaseConfig)
68
+ ::ActiveRecord::DatabaseConfigurations::DatabaseConfig.prepend(
69
+ ActiveRecord::DatabaseConfigurations::DatabaseConfig
70
+ )
61
71
 
62
72
  ::ActiveRecord::LogSubscriber.prepend(ActiveRecord::LogSubscriber)
63
73
  ::ActiveRecord::Migration.prepend(ActiveRecord::Migration)
@@ -77,8 +87,12 @@ module Switchman
77
87
  ::ActiveRecord::Relation.include(ActiveRecord::SpawnMethods)
78
88
  ::ActiveRecord::Relation.include(CallSuper)
79
89
 
80
- ::ActiveRecord::PredicateBuilder::AssociationQueryValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
81
- ::ActiveRecord::PredicateBuilder::PolymorphicArrayValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
90
+ ::ActiveRecord::PredicateBuilder::AssociationQueryValue.prepend(
91
+ ActiveRecord::PredicateBuilder::AssociationQueryValue
92
+ )
93
+ ::ActiveRecord::PredicateBuilder::PolymorphicArrayValue.prepend(
94
+ ActiveRecord::PredicateBuilder::AssociationQueryValue
95
+ )
82
96
 
83
97
  ::ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(ActiveRecord::Tasks::DatabaseTasks)
84
98
 
@@ -96,17 +110,18 @@ module Switchman
96
110
 
97
111
  ::ActiveRecord::ConnectionAdapters::TableDefinition.prepend(ActiveRecord::TableDefinition)
98
112
  end
99
- # Ensure that ActiveRecord::Base is always loaded before any app-level initializers can go try to load Switchman::Shard or we get a loop
113
+ # Ensure that ActiveRecord::Base is always loaded before any app-level
114
+ # initializers can go try to load Switchman::Shard or we get a loop
100
115
  ::ActiveRecord::Base
101
116
  end
102
117
 
103
- initializer 'switchman.error_patch', after: 'active_record.initialize_database' do
118
+ initializer "switchman.error_patch", after: "active_record.initialize_database" do
104
119
  ::ActiveSupport.on_load(:active_record) do
105
120
  ::StandardError.include(StandardError)
106
121
  end
107
122
  end
108
123
 
109
- initializer 'switchman.initialize_cache', before: :initialize_cache, after: 'active_record.initialize_database' do
124
+ initializer "switchman.initialize_cache", before: :initialize_cache, after: "active_record.initialize_database" do
110
125
  ::ActiveSupport::Cache.singleton_class.prepend(ActiveSupport::Cache::ClassMethods)
111
126
 
112
127
  # if we haven't already setup our cache map out-of-band, set it up from
@@ -130,11 +145,11 @@ module Switchman
130
145
  Switchman.config[:cache_map][::Rails.env] = value
131
146
  end
132
147
 
133
- middlewares = Switchman.config[:cache_map].values.map do |store|
148
+ middlewares = Switchman.config[:cache_map].values.filter_map do |store|
134
149
  store.middleware if store.respond_to?(:middleware)
135
- end.compact.uniq
150
+ end.uniq
136
151
  middlewares.each do |middleware|
137
- config.middleware.insert_before('Rack::Runtime', middleware)
152
+ config.middleware.insert_before("Rack::Runtime", middleware)
138
153
  end
139
154
 
140
155
  # prevent :initialize_cache from trying to (or needing to) set
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'etc'
3
+ require "etc"
4
4
 
5
5
  module Switchman
6
6
  class Environment
7
- def self.cpu_count(nproc_bin = 'nproc')
7
+ def self.cpu_count(nproc_bin = "nproc")
8
8
  return Etc.nprocessors if Etc.respond_to?(:nprocessors)
9
9
 
10
10
  `#{nproc_bin}`.to_i
@@ -3,7 +3,10 @@
3
3
  module Switchman
4
4
  module Errors
5
5
  class ManuallyCreatedShadowRecordError < RuntimeError
6
- def initialize(msg = "It looks like you're trying to manually create a shadow record. Please use Switchman::ActiveRecord::Base#save_shadow_record instead.")
6
+ DEFAULT_MSG = "It looks like you're trying to manually create a shadow record. " \
7
+ "Please use Switchman::ActiveRecord::Base#save_shadow_record instead."
8
+
9
+ def initialize(msg = DEFAULT_MSG)
7
10
  super
8
11
  end
9
12
  end
@@ -13,7 +13,7 @@ module Switchman
13
13
  end
14
14
 
15
15
  %w[update_all delete_all].each do |method|
16
- arg_params = RUBY_VERSION <= '2.8' ? '*args' : '*args, **kwargs'
16
+ arg_params = (RUBY_VERSION <= "2.8") ? "*args" : "*args, **kwargs"
17
17
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
18
18
  def #{method}(#{arg_params})
19
19
  db = Shard.current(connection_class_for_self).database_server
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'parallel'
3
+ require "parallel"
4
4
 
5
5
  module Switchman
6
6
  module Parallel
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'switchman/test_helper'
3
+ require "switchman/test_helper"
4
4
 
5
5
  module Switchman
6
6
  # including this module in your specs will give you several shards to
@@ -34,9 +34,9 @@ module Switchman
34
34
  groups = group.class.descendant_filtered_examples.map(&:example_group).uniq
35
35
  next unless groups.any? { |descendant_group| RSpecHelper.included_in?(descendant_group) }
36
36
 
37
- puts 'Setting up sharding for all specs...'
37
+ puts "Setting up sharding for all specs..."
38
38
  Shard.delete_all
39
- Switchman.cache.delete('default_shard')
39
+ Switchman.cache.delete("default_shard")
40
40
 
41
41
  @@shard1, @@shard2 = TestHelper.recreate_persistent_test_shards
42
42
  @@default_shard = Shard.default
@@ -48,7 +48,7 @@ module Switchman
48
48
  @@shard1 = @@shard1.create_new_shard
49
49
  @@shard2 = @@shard2.create_new_shard
50
50
  rescue => e
51
- warn 'Sharding setup FAILED!:'
51
+ warn "Sharding setup FAILED!:"
52
52
  while e
53
53
  warn "\n#{e}\n"
54
54
  warn e.backtrace
@@ -66,9 +66,9 @@ module Switchman
66
66
  # we'll re-persist in the group's `before :all`; we don't want them to exist
67
67
  # in the db before then
68
68
  Shard.delete_all
69
- Switchman.cache.delete('default_shard')
69
+ Switchman.cache.delete("default_shard")
70
70
  Shard.default(reload: true)
71
- puts 'Done!'
71
+ puts "Done!"
72
72
 
73
73
  main_pid = Process.pid
74
74
  at_exit do
@@ -76,7 +76,7 @@ module Switchman
76
76
 
77
77
  # preserve rspec's exit status
78
78
  status = $!.is_a?(::SystemExit) ? $!.status : nil
79
- puts 'Tearing down sharding for all specs'
79
+ puts "Tearing down sharding for all specs"
80
80
  @@shard1.database_server.destroy unless @@shard1.database_server == Shard.default.database_server
81
81
  unless @@keep_the_shards
82
82
  @@shard1.drop_database
@@ -95,7 +95,7 @@ module Switchman
95
95
  dup = @@default_shard.dup
96
96
  dup.id = @@default_shard.id
97
97
  dup.save!
98
- Switchman.cache.delete('default_shard')
98
+ Switchman.cache.delete("default_shard")
99
99
  Shard.default(reload: true)
100
100
  dup = @@shard1.dup
101
101
  dup.id = @@shard1.id
@@ -107,7 +107,7 @@ module Switchman
107
107
  end
108
108
 
109
109
  klass.before do
110
- raise 'Sharding did not set up correctly' if @@sharding_failed
110
+ raise "Sharding did not set up correctly" if @@sharding_failed
111
111
 
112
112
  Shard.clear_cache
113
113
  if use_transactional_tests
@@ -132,7 +132,7 @@ module Switchman
132
132
  klass.after(:all) do
133
133
  # Don't truncate because that can create some fun cross-connection lock contention
134
134
  Shard.delete_all
135
- Switchman.cache.delete('default_shard')
135
+ Switchman.cache.delete("default_shard")
136
136
  Shard.default(reload: true)
137
137
  end
138
138
  end
@@ -36,13 +36,15 @@ module Switchman
36
36
 
37
37
  # Now find the actual record, if it exists
38
38
  @default = begin
39
- find_cached('default_shard') { Shard.where(default: true).take } || default
39
+ find_cached("default_shard") { Shard.where(default: true).take } || default
40
40
  rescue
41
41
  default
42
42
  end
43
43
 
44
44
  # make sure this is not erroneously cached
45
- @default.database_server.remove_instance_variable(:@primary_shard) if @default.database_server.instance_variable_defined?(:@primary_shard)
45
+ if @default.database_server.instance_variable_defined?(:@primary_shard)
46
+ @default.database_server.remove_instance_variable(:@primary_shard)
47
+ end
46
48
 
47
49
  # and finally, check for cached references to the default shard on the existing connection
48
50
  sharded_models.each do |klass|
@@ -75,28 +77,30 @@ module Switchman
75
77
  klass.current_switchman_shard != shard
76
78
 
77
79
  (activated_classes ||= []) << klass
78
- klass.connected_to_stack << { shard: shard.database_server.id.to_sym, klasses: [klass], switchman_shard: shard }
80
+ klass.connected_to_stack << { shard: shard.database_server.id.to_sym,
81
+ klasses: [klass],
82
+ switchman_shard: shard }
79
83
  end
80
84
  activated_classes
81
85
  end
82
86
 
83
87
  def active_shards
84
- sharded_models.map do |klass|
88
+ sharded_models.filter_map do |klass|
85
89
  [klass, current(klass)]
86
- end.compact.to_h
90
+ end.to_h
87
91
  end
88
92
 
89
93
  def lookup(id)
90
94
  id_i = id.to_i
91
- return current if id_i == current.id || id == 'self'
92
- return default if id_i == default.id || id.nil? || id == 'default'
95
+ return current if id_i == current.id || id == "self"
96
+ return default if id_i == default.id || id.nil? || id == "default"
93
97
 
94
98
  id = id_i
95
99
  raise ArgumentError if id.zero?
96
100
 
97
101
  unless cached_shards.key?(id)
98
102
  cached_shards[id] = Shard.default.activate do
99
- find_cached(['shard', id]) { find_by(id: id) }
103
+ find_cached(["shard", id]) { find_by(id: id) }
100
104
  end
101
105
  end
102
106
  cached_shards[id]
@@ -140,13 +144,15 @@ module Switchman
140
144
  parallel = 0 if parallel == false || parallel.nil?
141
145
 
142
146
  scope ||= Shard.all
143
- scope = scope.order(::Arel.sql('database_server_id IS NOT NULL, database_server_id, id')) if ::ActiveRecord::Relation === scope && scope.order_values.empty?
147
+ if ::ActiveRecord::Relation === scope && scope.order_values.empty?
148
+ scope = scope.order(::Arel.sql("database_server_id IS NOT NULL, database_server_id, id"))
149
+ end
144
150
 
145
151
  if parallel > 1
146
152
  if ::ActiveRecord::Relation === scope
147
153
  # still need a post-uniq, cause the default database server could be NULL or Rails.env in the db
148
- database_servers = scope.reorder('database_server_id').select(:database_server_id).distinct.
149
- map(&:database_server).compact.uniq
154
+ database_servers = scope.reorder("database_server_id").select(:database_server_id).distinct
155
+ .filter_map(&:database_server).uniq
150
156
  # nothing to do
151
157
  return if database_servers.count.zero?
152
158
 
@@ -163,14 +169,14 @@ module Switchman
163
169
  ::ActiveRecord::Base.clear_all_connections!
164
170
 
165
171
  parent_process_name = `ps -ocommand= -p#{Process.pid}`.slice(/#{$0}.*/)
166
- ret = ::Parallel.map(scopes, in_processes: scopes.length > 1 ? parallel : 0) do |server, subscope|
172
+ ret = ::Parallel.map(scopes, in_processes: (scopes.length > 1) ? parallel : 0) do |server, subscope|
167
173
  name = server.id
168
174
  last_description = name
169
175
 
170
176
  begin
171
177
  max_length = 128 - name.length - 3
172
178
  short_parent_name = parent_process_name[0..max_length] if max_length >= 0
173
- new_title = [short_parent_name, name].join(' ')
179
+ new_title = [short_parent_name, name].join(" ")
174
180
  Process.setproctitle(new_title)
175
181
  Switchman.config[:on_fork_proc]&.call
176
182
  with_each_shard(subscope, classes, exception: exception, output: :decorated) do
@@ -187,8 +193,9 @@ module Switchman
187
193
  unless errors.empty?
188
194
  raise errors.first.exception if errors.length == 1
189
195
 
196
+ errors_desc = errors.map(&:name).sort.join(", ")
190
197
  raise Errors::ParallelShardExecError,
191
- "The following database server(s) did not finish processing cleanly: #{errors.map(&:name).sort.join(', ')}",
198
+ "The following database server(s) did not finish processing cleanly: #{errors_desc}",
192
199
  cause: errors.first.exception
193
200
  end
194
201
 
@@ -467,7 +474,7 @@ module Switchman
467
474
  end
468
475
 
469
476
  def description
470
- [database_server.id, name].compact.join(':')
477
+ [database_server.id, name].compact.join(":")
471
478
  end
472
479
 
473
480
  # Shards are always on the default shard
@@ -501,7 +508,7 @@ module Switchman
501
508
  end
502
509
 
503
510
  def drop_database
504
- raise('Cannot drop the database of the default shard') if default?
511
+ raise("Cannot drop the database of the default shard") if default?
505
512
  return unless read_attribute(:name)
506
513
 
507
514
  begin
@@ -510,12 +517,12 @@ module Switchman
510
517
  drop_statement = sharding_config[adapter]&.[](:drop_statement)
511
518
  drop_statement ||= sharding_config[:drop_statement]
512
519
  if drop_statement
513
- drop_statement = Array(drop_statement).dup.
514
- map { |statement| statement.gsub('%{name}', name) }
520
+ drop_statement = Array(drop_statement).dup
521
+ .map { |statement| statement.gsub("%{name}", name) }
515
522
  end
516
523
 
517
524
  case adapter
518
- when 'mysql', 'mysql2'
525
+ when "mysql", "mysql2"
519
526
  activate do
520
527
  ::GuardRail.activate(:deploy) do
521
528
  drop_statement ||= "DROP DATABASE #{name}"
@@ -524,7 +531,7 @@ module Switchman
524
531
  end
525
532
  end
526
533
  end
527
- when 'postgresql'
534
+ when "postgresql"
528
535
  activate do
529
536
  ::GuardRail.activate(:deploy) do
530
537
  # Shut up, Postgres!
@@ -561,7 +568,7 @@ module Switchman
561
568
  end
562
569
 
563
570
  def destroy
564
- raise('Cannot destroy the default shard') if default?
571
+ raise("Cannot destroy the default shard") if default?
565
572
 
566
573
  super
567
574
  end
@@ -570,8 +577,8 @@ module Switchman
570
577
 
571
578
  def clear_cache
572
579
  Shard.default.activate do
573
- Switchman.cache.delete(['shard', id].join('/'))
574
- Switchman.cache.delete('default_shard') if default?
580
+ Switchman.cache.delete(["shard", id].join("/"))
581
+ Switchman.cache.delete("default_shard") if default?
575
582
  end
576
583
  self.class.clear_cache
577
584
  end
@@ -16,7 +16,11 @@ module Switchman
16
16
  payload[:shard] = {
17
17
  database_server_id: shard.database_server.id,
18
18
  id: shard.id,
19
- env: ::Rails.version < '7.0' ? @shard_host.pool.connection_klass&.current_role : @shard_host.pool.connection_class&.current_role
19
+ env: if ::Rails.version < "7.0"
20
+ @shard_host.pool.connection_klass&.current_role
21
+ else
22
+ @shard_host.pool.connection_class&.current_role
23
+ end
20
24
  }
21
25
  end
22
26
  super name, payload
@@ -65,7 +65,7 @@ module Switchman
65
65
  if server == Shard.default.database_server
66
66
  server.shards.where(name: name).first
67
67
  else
68
- shard = Shard.where('database_server_id IS NOT NULL AND name=?', name).first
68
+ shard = Shard.where("database_server_id IS NOT NULL AND name=?", name).first
69
69
  # if somehow databases got created in a different order, change the shard to match
70
70
  shard.database_server = server if shard
71
71
  shard
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = '3.4.2'
4
+ VERSION = "3.5.1"
5
5
  end
data/lib/switchman.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'guard_rail'
4
- require 'zeitwerk'
3
+ require "guard_rail"
4
+ require "zeitwerk"
5
5
 
6
6
  class SwitchmanInflector < Zeitwerk::GemInflector
7
7
  def camelize(basename, abspath)
8
8
  if basename =~ /\Apostgresql_(.*)/
9
- 'PostgreSQL' + super($1, abspath)
9
+ "PostgreSQL" + super($1, abspath)
10
10
  else
11
11
  super
12
12
  end
@@ -18,6 +18,8 @@ loader.inflector = SwitchmanInflector.new(__FILE__)
18
18
  loader.setup
19
19
 
20
20
  module Switchman
21
+ Deprecation = ::ActiveSupport::Deprecation.new("4.0", "Switchman")
22
+
21
23
  def self.config
22
24
  # TODO: load from yaml
23
25
  @config ||= {}
@@ -32,7 +34,13 @@ module Switchman
32
34
  end
33
35
 
34
36
  def self.foreign_key_check(name, type, limit: nil)
35
- puts "WARNING: All foreign keys need to be 8-byte integers. #{name} looks like a foreign key. If so, please add the option: `:limit => 8`" if name.to_s =~ /_id\z/ && type.to_s == 'integer' && limit.to_i < 8
37
+ return unless name.to_s.end_with?("_id") && type.to_s == "integer" && limit.to_i < 8
38
+
39
+ puts <<~TEXT.squish
40
+ WARNING: All foreign keys need to be 8-byte integers.
41
+ #{name} looks like a foreign key.
42
+ If so, please add the option: `:limit => 8`
43
+ TEXT
36
44
  end
37
45
 
38
46
  class OrderOnMultiShardQuery < RuntimeError; end