switchman 3.3.6 → 4.2.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.
Files changed (47) 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/abstract_adapter.rb +10 -6
  6. data/lib/switchman/active_record/associations.rb +72 -49
  7. data/lib/switchman/active_record/attribute_methods.rb +89 -44
  8. data/lib/switchman/active_record/base.rb +109 -40
  9. data/lib/switchman/active_record/calculations.rb +90 -54
  10. data/lib/switchman/active_record/connection_handler.rb +18 -0
  11. data/lib/switchman/active_record/connection_pool.rb +41 -23
  12. data/lib/switchman/active_record/database_configurations.rb +23 -13
  13. data/lib/switchman/active_record/finder_methods.rb +20 -14
  14. data/lib/switchman/active_record/log_subscriber.rb +3 -6
  15. data/lib/switchman/active_record/migration.rb +35 -12
  16. data/lib/switchman/active_record/pending_migration_connection.rb +17 -0
  17. data/lib/switchman/active_record/persistence.rb +30 -0
  18. data/lib/switchman/active_record/postgresql_adapter.rb +37 -22
  19. data/lib/switchman/active_record/predicate_builder.rb +2 -2
  20. data/lib/switchman/active_record/query_cache.rb +26 -17
  21. data/lib/switchman/active_record/query_methods.rb +148 -44
  22. data/lib/switchman/active_record/reflection.rb +9 -2
  23. data/lib/switchman/active_record/relation.rb +87 -17
  24. data/lib/switchman/active_record/spawn_methods.rb +3 -7
  25. data/lib/switchman/active_record/statement_cache.rb +4 -4
  26. data/lib/switchman/active_record/table_definition.rb +1 -1
  27. data/lib/switchman/active_record/tasks/database_tasks.rb +6 -1
  28. data/lib/switchman/active_record/test_fixtures.rb +71 -25
  29. data/lib/switchman/active_support/cache.rb +9 -4
  30. data/lib/switchman/arel.rb +16 -25
  31. data/lib/switchman/call_super.rb +2 -8
  32. data/lib/switchman/database_server.rb +67 -48
  33. data/lib/switchman/default_shard.rb +14 -3
  34. data/lib/switchman/engine.rb +35 -23
  35. data/lib/switchman/environment.rb +2 -2
  36. data/lib/switchman/errors.rb +13 -0
  37. data/lib/switchman/guard_rail/relation.rb +1 -2
  38. data/lib/switchman/parallel.rb +6 -6
  39. data/lib/switchman/r_spec_helper.rb +12 -11
  40. data/lib/switchman/shard.rb +168 -68
  41. data/lib/switchman/sharded_instrumenter.rb +9 -3
  42. data/lib/switchman/standard_error.rb +4 -0
  43. data/lib/switchman/test_helper.rb +3 -3
  44. data/lib/switchman/version.rb +1 -1
  45. data/lib/switchman.rb +27 -15
  46. data/lib/tasks/switchman.rake +96 -60
  47. metadata +28 -173
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,21 +18,33 @@ loader.inflector = SwitchmanInflector.new(__FILE__)
18
18
  loader.setup
19
19
 
20
20
  module Switchman
21
- def self.config
22
- # TODO: load from yaml
23
- @config ||= {}
24
- end
21
+ Deprecation = ::ActiveSupport::Deprecation.new("4.0", "Switchman")
25
22
 
26
- def self.cache
27
- (@cache.respond_to?(:call) ? @cache.call : @cache) || ::Rails.cache
28
- end
23
+ class << self
24
+ attr_writer :cache
29
25
 
30
- def self.cache=(cache)
31
- @cache = cache
32
- end
26
+ def config
27
+ # TODO: load from yaml
28
+ @config ||= {}
29
+ end
30
+
31
+ def cache
32
+ (@cache.respond_to?(:call) ? @cache.call : @cache) || ::Rails.cache
33
+ end
34
+
35
+ def region
36
+ config[:region]
37
+ end
33
38
 
34
- 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
39
+ def foreign_key_check(name, type, limit: nil)
40
+ return unless name.to_s.end_with?("_id") && type.to_s == "integer" && limit.to_i < 8
41
+
42
+ puts <<~TEXT.squish
43
+ WARNING: All foreign keys need to be 8-byte integers.
44
+ #{name} looks like a foreign key.
45
+ If so, please add the option: `:limit => 8`
46
+ TEXT
47
+ end
36
48
  end
37
49
 
38
50
  class OrderOnMultiShardQuery < RuntimeError; end
@@ -1,40 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # In rails 7.0+ if you have only 1 db in the env it doesn't try to do explicit activation
4
- # (and for rails purposes we only have one db per env because each database server is a separate env)
5
- if Rails.version < '7.0'
6
- task_prefix = ::Rake::Task.task_defined?('app:db:migrate') ? 'app:db' : 'db'
7
- ::Rake::Task["#{task_prefix}:migrate"].clear_actions.enhance do
8
- ::ActiveRecord::Tasks::DatabaseTasks.migrate
9
- # Ensure this doesn't blow up when running inside the dummy app
10
- Rake::Task["#{task_prefix}:_dump"].invoke
11
- end
12
- end
13
-
14
3
  module Switchman
15
4
  module Rake
16
- def self.filter_database_servers(&block)
17
- chain = filter_database_servers_chain # use a local variable so that the current chain is closed over in the following lambda
18
- @filter_database_servers_chain = ->(servers) { block.call(servers, chain) }
5
+ def self.filter_database_servers
6
+ # use a local variable so that the current chain is closed over in the following lambda
7
+ chain = filter_database_servers_chain
8
+ @filter_database_servers_chain = ->(servers) { yield(servers, chain) }
19
9
  end
20
10
 
21
11
  def self.scope(base_scope = Shard,
22
- database_server: ENV['DATABASE_SERVER'],
23
- shard: ENV['SHARD'])
12
+ database_server: ENV.fetch("DATABASE_SERVER", nil),
13
+ shard: ENV.fetch("SHARD", nil))
24
14
  servers = DatabaseServer.all
25
15
 
26
16
  if database_server
27
17
  servers = database_server
28
- if servers.first == '-'
18
+ if servers.first == "-"
29
19
  negative = true
30
20
  servers = servers[1..]
31
21
  end
32
- servers = servers.split(',')
33
- open = servers.delete('open')
22
+ servers = servers.split(",")
23
+ open = servers.delete("open")
34
24
 
35
- servers = servers.map { |server| DatabaseServer.find(server) }.compact
25
+ servers = servers.filter_map { |server| DatabaseServer.find(server) }
36
26
  if open
37
- open_servers = DatabaseServer.all.select { |server| server.config[:open] }
27
+ open_servers = DatabaseServer.select { |server| server.config[:open] }
38
28
  servers.concat(open_servers)
39
29
  servers << DatabaseServer.find(nil) if open_servers.empty?
40
30
  servers.uniq!
@@ -42,9 +32,22 @@ module Switchman
42
32
  servers = DatabaseServer.all - servers if negative
43
33
  end
44
34
 
35
+ ENV["REGION"]&.split(",")&.each do |region|
36
+ method = :select!
37
+ if region[0] == "-"
38
+ method = :reject!
39
+ region = region[1..]
40
+ end
41
+ if region == "self"
42
+ servers.send(method, &:in_current_region?)
43
+ else
44
+ servers.send(method) { |server| server.in_region?(region) }
45
+ end
46
+ end
47
+
45
48
  servers = filter_database_servers_chain.call(servers)
46
49
 
47
- scope = base_scope.order(::Arel.sql('database_server_id IS NOT NULL, database_server_id, id'))
50
+ scope = base_scope.order(::Arel.sql("database_server_id IS NOT NULL, database_server_id, id"))
48
51
  if servers != DatabaseServer.all
49
52
  database_server_ids = servers.map(&:id)
50
53
  database_server_ids << nil if servers.include?(Shard.default.database_server)
@@ -57,36 +60,81 @@ module Switchman
57
60
  end
58
61
 
59
62
  def self.options
60
- { parallel: ENV['PARALLEL'].to_i }
63
+ { exception: (ENV["FAIL_FAST"] == "0") ? :defer : :raise, parallel: ENV["PARALLEL"].to_i }
61
64
  end
62
65
 
63
66
  # classes - an array or proc, to activate as the current shard during the
64
67
  # task.
65
68
  def self.shardify_task(task_name, classes: [::ActiveRecord::Base])
69
+ log_format = ENV.fetch("LOG_FORMAT", nil)
66
70
  old_task = ::Rake::Task[task_name]
67
71
  old_actions = old_task.actions.dup
68
72
  old_task.actions.clear
69
73
 
70
74
  old_task.enhance do |*task_args|
71
75
  if ::Rails.env.test?
72
- require 'switchman/test_helper'
76
+ require "switchman/test_helper"
73
77
  TestHelper.recreate_persistent_test_shards(dont_create: true)
74
78
  end
75
79
 
76
80
  ::GuardRail.activate(:deploy) do
77
81
  Shard.default.database_server.unguard do
78
82
  classes = classes.call if classes.respond_to?(:call)
79
- Shard.with_each_shard(scope, classes, **options) do
83
+
84
+ # We don't want the shard status messages to be wrapped using a custom log transfomer
85
+ original_stderr = $stderr
86
+ original_stdout = $stdout
87
+ output = if log_format == "json"
88
+ lambda { |msg|
89
+ JSON.dump(shard: Shard.current.id,
90
+ database_server: Shard.current.database_server.id,
91
+ type: "log",
92
+ message: msg)
93
+ }
94
+ else
95
+ nil
96
+ end
97
+ Shard.with_each_shard(scope, classes, output:, **options) do
80
98
  shard = Shard.current
81
- puts "#{shard.id}: #{shard.description}"
99
+
100
+ if log_format == "json"
101
+ original_stdout.puts JSON.dump(
102
+ shard: shard.id,
103
+ database_server: shard.database_server.id,
104
+ type: "started"
105
+ )
106
+ else
107
+ original_stdout.puts "#{shard.id}: #{shard.description}"
108
+ end
82
109
 
83
110
  shard.database_server.unguard do
84
111
  old_actions.each { |action| action.call(*task_args) }
85
112
  end
113
+
114
+ if log_format == "json"
115
+ original_stdout.puts JSON.dump(
116
+ shard: shard.id,
117
+ database_server: shard.database_server.id,
118
+ type: "completed"
119
+ )
120
+ end
86
121
  nil
122
+ rescue => e
123
+ if log_format == "json"
124
+ original_stderr.puts JSON.dump(
125
+ shard: shard.id,
126
+ database_server: shard.database_server.id,
127
+ type: "failed",
128
+ message: e.full_message
129
+ )
130
+ end
131
+
132
+ raise
87
133
  end
88
134
  rescue => e
89
- warn "Exception from #{e.current_shard.id}: #{e.current_shard.description}:\n#{e.full_message}" if options[:parallel] != 0
135
+ if options[:parallel] != 0
136
+ warn "Exception from #{e.current_shard.id}: #{e.current_shard.description}:\n#{e.full_message}"
137
+ end
90
138
  raise
91
139
  end
92
140
  end
@@ -98,7 +146,7 @@ module Switchman
98
146
  end
99
147
 
100
148
  def self.shard_scope(scope, raw_shard_ids)
101
- raw_shard_ids = raw_shard_ids.split(',')
149
+ raw_shard_ids = raw_shard_ids.split(",")
102
150
 
103
151
  shard_ids = []
104
152
  negative_shard_ids = []
@@ -108,13 +156,13 @@ module Switchman
108
156
 
109
157
  raw_shard_ids.each do |id|
110
158
  case id
111
- when 'default'
159
+ when "default"
112
160
  shard_ids << Shard.default.id
113
- when '-default'
161
+ when "-default"
114
162
  negative_shard_ids << Shard.default.id
115
- when 'primary'
163
+ when "primary"
116
164
  shard_ids.concat(Shard.primary.pluck(:id))
117
- when '-primary'
165
+ when "-primary"
118
166
  negative_shard_ids.concat(Shard.primary.pluck(:id))
119
167
  when /^(-?)(\d+)?\.\.(\.)?(\d+)?$/
120
168
  negative, start, open, finish = $1.present?, $2, $3.present?, $4
@@ -122,8 +170,8 @@ module Switchman
122
170
 
123
171
  range = []
124
172
  range << "id>=#{start}" if start
125
- range << "id<#{'=' unless open}#{finish}" if finish
126
- (negative ? negative_ranges : ranges) << "(#{range.join(' AND ')})"
173
+ range << "id<#{"=" unless open}#{finish}" if finish
174
+ (negative ? negative_ranges : ranges) << "(#{range.join(" AND ")})"
127
175
  when /^-(\d+)$/
128
176
  negative_shard_ids << $1.to_i
129
177
  when /^\d+$/
@@ -151,21 +199,21 @@ module Switchman
151
199
  select = []
152
200
  if index != 1
153
201
  subscope = subscope.offset(per_chunk * (index - 1))
154
- select << 'MIN(id) AS min_id'
202
+ select << "MIN(id) AS min_id"
155
203
  end
156
204
  if index != denominator
157
205
  subscope = subscope.limit(per_chunk)
158
- select << 'MAX(id) AS max_id'
206
+ select << "MAX(id) AS max_id"
159
207
  end
160
208
 
161
- result = Shard.from(subscope).select(select.join(', ')).to_a.first
209
+ result = Shard.from(subscope).select(select.join(", ")).to_a.first
162
210
  range = case index
163
211
  when 1
164
- "id<=#{result['max_id']}"
212
+ "id<=#{result["max_id"]}"
165
213
  when denominator
166
- "id>=#{result['min_id']}"
214
+ "id>=#{result["min_id"]}"
167
215
  else
168
- "(id>=#{result['min_id']} AND id<=#{result['max_id']})"
216
+ "(id>=#{result["min_id"]} AND id<=#{result["max_id"]})"
169
217
  end
170
218
 
171
219
  (numerator.negative? ? negative_ranges : ranges) << range
@@ -186,16 +234,16 @@ module Switchman
186
234
 
187
235
  conditions = []
188
236
  positive_queries = []
189
- positive_queries << ranges.join(' OR ') unless ranges.empty?
237
+ positive_queries << ranges.join(" OR ") unless ranges.empty?
190
238
  unless shard_ids.empty?
191
- positive_queries << 'id IN (?)'
239
+ positive_queries << "id IN (?)"
192
240
  conditions << shard_ids
193
241
  end
194
- positive_query = positive_queries.join(' OR ')
242
+ positive_query = positive_queries.join(" OR ")
195
243
  scope = scope.where(positive_query, *conditions) unless positive_queries.empty?
196
244
 
197
- scope = scope.where("NOT (#{negative_ranges.join(' OR')})") unless negative_ranges.empty?
198
- scope = scope.where('id NOT IN (?)', negative_shard_ids) unless negative_shard_ids.empty?
245
+ scope = scope.where("NOT (#{negative_ranges.join(" OR")})") unless negative_ranges.empty?
246
+ scope = scope.where("id NOT IN (?)", negative_shard_ids) unless negative_shard_ids.empty?
199
247
  scope
200
248
  end
201
249
 
@@ -206,21 +254,9 @@ module Switchman
206
254
 
207
255
  module ActiveRecord
208
256
  module PostgreSQLDatabaseTasks
209
- def structure_dump(filename, extra_flags = nil)
210
- set_psql_env
211
- args = ['--schema-only', '--no-privileges', '--no-owner', '--file', filename]
212
- args.concat(Array(extra_flags)) if extra_flags
213
- shard = Shard.current.name
214
- serialized_search_path = shard
215
- args << "--schema=#{Shellwords.escape(shard)}"
216
-
217
- ignore_tables = ::ActiveRecord::SchemaDumper.ignore_tables
218
- args += ignore_tables.flat_map { |table| ['-T', table] } if ignore_tables.any?
219
-
220
- args << db_config.database
221
- run_cmd('pg_dump', args, 'dumping')
222
- remove_sql_header_comments(filename)
223
- File.open(filename, 'a') { |f| f << "SET search_path TO #{serialized_search_path};\n\n" }
257
+ def structure_dump(...)
258
+ ::ActiveRecord.dump_schemas = Switchman::Shard.current.name
259
+ super
224
260
  end
225
261
  end
226
262
  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: 3.3.6
4
+ version: 4.2.5
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: 2023-03-21 00:00:00.000000000 Z
13
+ date: 2026-05-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -18,222 +18,74 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 6.1.4
21
+ version: '7.1'
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '7.1'
24
+ version: '8.1'
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
28
28
  requirements:
29
29
  - - ">="
30
30
  - !ruby/object:Gem::Version
31
- version: 6.1.4
31
+ version: '7.1'
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '7.1'
34
+ version: '8.1'
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: guardrail
37
37
  requirement: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 3.0.1
41
+ version: 3.1.0
42
42
  type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: 3.0.1
48
+ version: 3.1.0
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: parallel
51
- requirement: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: '1.22'
56
- type: :runtime
57
- prerelease: false
58
- version_requirements: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - "~>"
61
- - !ruby/object:Gem::Version
62
- version: '1.22'
63
- - !ruby/object:Gem::Dependency
64
- name: railties
65
51
  requirement: !ruby/object:Gem::Requirement
66
52
  requirements:
67
53
  - - ">="
68
54
  - !ruby/object:Gem::Version
69
- version: '6.1'
55
+ version: '1.22'
70
56
  - - "<"
71
57
  - !ruby/object:Gem::Version
72
- version: '7.1'
58
+ version: '3.0'
73
59
  type: :runtime
74
60
  prerelease: false
75
61
  version_requirements: !ruby/object:Gem::Requirement
76
62
  requirements:
77
63
  - - ">="
78
64
  - !ruby/object:Gem::Version
79
- version: '6.1'
65
+ version: '1.22'
80
66
  - - "<"
81
67
  - !ruby/object:Gem::Version
82
- version: '7.1'
83
- - !ruby/object:Gem::Dependency
84
- name: appraisal
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 2.3.0
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 2.3.0
68
+ version: '3.0'
97
69
  - !ruby/object:Gem::Dependency
98
- name: byebug
70
+ name: railties
99
71
  requirement: !ruby/object:Gem::Requirement
100
72
  requirements:
101
73
  - - ">="
102
74
  - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: pg
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '1.2'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '1.2'
125
- - !ruby/object:Gem::Dependency
126
- name: pry
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
75
+ version: '7.1'
76
+ - - "<"
130
77
  - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
78
+ version: '8.1'
79
+ type: :runtime
133
80
  prerelease: false
134
81
  version_requirements: !ruby/object:Gem::Requirement
135
82
  requirements:
136
83
  - - ">="
137
84
  - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rake
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '13.0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '13.0'
153
- - !ruby/object:Gem::Dependency
154
- name: rspec-mocks
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '3.5'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '3.5'
167
- - !ruby/object:Gem::Dependency
168
- name: rspec-rails
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: '4.0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: '4.0'
181
- - !ruby/object:Gem::Dependency
182
- name: rubocop
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '1.10'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '1.10'
195
- - !ruby/object:Gem::Dependency
196
- name: rubocop-rake
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '0.5'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: '0.5'
209
- - !ruby/object:Gem::Dependency
210
- name: rubocop-rspec
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - "~>"
214
- - !ruby/object:Gem::Version
215
- version: '2.2'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - "~>"
221
- - !ruby/object:Gem::Version
222
- version: '2.2'
223
- - !ruby/object:Gem::Dependency
224
- name: simplecov
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - "~>"
228
- - !ruby/object:Gem::Version
229
- version: '0.15'
230
- type: :development
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - "~>"
85
+ version: '7.1'
86
+ - - "<"
235
87
  - !ruby/object:Gem::Version
236
- version: '0.15'
88
+ version: '8.1'
237
89
  description: Sharding
238
90
  email:
239
91
  - cody@instructure.com
@@ -255,6 +107,7 @@ files:
255
107
  - lib/switchman/active_record/attribute_methods.rb
256
108
  - lib/switchman/active_record/base.rb
257
109
  - lib/switchman/active_record/calculations.rb
110
+ - lib/switchman/active_record/connection_handler.rb
258
111
  - lib/switchman/active_record/connection_pool.rb
259
112
  - lib/switchman/active_record/database_configurations.rb
260
113
  - lib/switchman/active_record/database_configurations/database_config.rb
@@ -262,6 +115,7 @@ files:
262
115
  - lib/switchman/active_record/log_subscriber.rb
263
116
  - lib/switchman/active_record/migration.rb
264
117
  - lib/switchman/active_record/model_schema.rb
118
+ - lib/switchman/active_record/pending_migration_connection.rb
265
119
  - lib/switchman/active_record/persistence.rb
266
120
  - lib/switchman/active_record/postgresql_adapter.rb
267
121
  - lib/switchman/active_record/predicate_builder.rb
@@ -301,7 +155,8 @@ licenses:
301
155
  - MIT
302
156
  metadata:
303
157
  rubygems_mfa_required: 'true'
304
- post_install_message:
158
+ source_code_uri: https://github.com/instructure/switchman
159
+ post_install_message:
305
160
  rdoc_options: []
306
161
  require_paths:
307
162
  - lib
@@ -309,15 +164,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
309
164
  requirements:
310
165
  - - ">="
311
166
  - !ruby/object:Gem::Version
312
- version: '2.7'
167
+ version: '3.2'
313
168
  required_rubygems_version: !ruby/object:Gem::Requirement
314
169
  requirements:
315
170
  - - ">="
316
171
  - !ruby/object:Gem::Version
317
172
  version: '0'
318
173
  requirements: []
319
- rubygems_version: 3.1.6
320
- signing_key:
174
+ rubygems_version: 3.4.19
175
+ signing_key:
321
176
  specification_version: 4
322
177
  summary: Rails sharding magic
323
178
  test_files: []