switchman 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +10 -2
  3. data/app/models/switchman/shard.rb +234 -270
  4. data/app/models/switchman/unsharded_record.rb +7 -0
  5. data/db/migrate/20130328212039_create_switchman_shards.rb +1 -1
  6. data/db/migrate/20130328224244_create_default_shard.rb +5 -5
  7. data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +1 -0
  8. data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
  9. data/db/migrate/20180828192111_add_timestamps_to_shards.rb +7 -5
  10. data/db/migrate/20190114212900_add_unique_name_indexes.rb +5 -3
  11. data/lib/switchman.rb +3 -3
  12. data/lib/switchman/action_controller/caching.rb +2 -2
  13. data/lib/switchman/active_record/abstract_adapter.rb +1 -0
  14. data/lib/switchman/active_record/association.rb +78 -85
  15. data/lib/switchman/active_record/attribute_methods.rb +58 -52
  16. data/lib/switchman/active_record/base.rb +58 -59
  17. data/lib/switchman/active_record/calculations.rb +73 -66
  18. data/lib/switchman/active_record/connection_pool.rb +14 -41
  19. data/lib/switchman/active_record/database_configurations.rb +34 -0
  20. data/lib/switchman/active_record/database_configurations/database_config.rb +13 -0
  21. data/lib/switchman/active_record/finder_methods.rb +11 -16
  22. data/lib/switchman/active_record/log_subscriber.rb +4 -8
  23. data/lib/switchman/active_record/migration.rb +6 -15
  24. data/lib/switchman/active_record/model_schema.rb +1 -1
  25. data/lib/switchman/active_record/persistence.rb +4 -6
  26. data/lib/switchman/active_record/postgresql_adapter.rb +42 -53
  27. data/lib/switchman/active_record/predicate_builder.rb +1 -1
  28. data/lib/switchman/active_record/query_cache.rb +18 -19
  29. data/lib/switchman/active_record/query_methods.rb +172 -181
  30. data/lib/switchman/active_record/reflection.rb +6 -10
  31. data/lib/switchman/active_record/relation.rb +27 -21
  32. data/lib/switchman/active_record/spawn_methods.rb +27 -29
  33. data/lib/switchman/active_record/statement_cache.rb +18 -35
  34. data/lib/switchman/active_record/tasks/database_tasks.rb +16 -0
  35. data/lib/switchman/active_support/cache.rb +3 -5
  36. data/lib/switchman/arel.rb +13 -8
  37. data/lib/switchman/database_server.rb +121 -142
  38. data/lib/switchman/default_shard.rb +52 -16
  39. data/lib/switchman/engine.rb +61 -57
  40. data/lib/switchman/environment.rb +4 -8
  41. data/lib/switchman/errors.rb +1 -0
  42. data/lib/switchman/guard_rail.rb +6 -19
  43. data/lib/switchman/guard_rail/relation.rb +5 -7
  44. data/lib/switchman/r_spec_helper.rb +29 -37
  45. data/lib/switchman/rails.rb +14 -12
  46. data/lib/switchman/schema_cache.rb +1 -1
  47. data/lib/switchman/sharded_instrumenter.rb +1 -1
  48. data/lib/switchman/standard_error.rb +15 -3
  49. data/lib/switchman/test_helper.rb +6 -10
  50. data/lib/switchman/version.rb +1 -1
  51. data/lib/tasks/switchman.rake +54 -69
  52. metadata +100 -44
  53. data/lib/switchman/active_record/batches.rb +0 -11
  54. data/lib/switchman/active_record/connection_handler.rb +0 -172
  55. data/lib/switchman/active_record/where_clause_factory.rb +0 -36
  56. data/lib/switchman/connection_pool_proxy.rb +0 -169
@@ -1,18 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Switchman::Rails
4
- module ClassMethods
5
- def self.prepended(klass)
6
- # in Rails 4+, the Rails.cache= method was used during bootstrap to set
7
- # Rails.cache(_without_sharding) to the value from the config file. but now
8
- # that that's done (the bootstrap happened before this module is included
9
- # into Rails), we want to make sure no one tries to assign to Rails.cache,
10
- # because it would be wrong w.r.t. sharding.
11
- klass.send(:remove_method, :cache=)
12
- end
3
+ module Switchman
4
+ module Rails
5
+ module ClassMethods
6
+ def self.prepended(klass)
7
+ # in Rails 4+, the Rails.cache= method was used during bootstrap to set
8
+ # Rails.cache(_without_sharding) to the value from the config file. but now
9
+ # that that's done (the bootstrap happened before this module is included
10
+ # into Rails), we want to make sure no one tries to assign to Rails.cache,
11
+ # because it would be wrong w.r.t. sharding.
12
+ klass.send(:remove_method, :cache=)
13
+ end
13
14
 
14
- def cache
15
- Switchman::Shard.current.database_server.cache_store
15
+ def cache
16
+ Switchman::Shard.current.database_server.cache_store
17
+ end
16
18
  end
17
19
  end
18
20
  end
@@ -12,7 +12,7 @@ module Switchman
12
12
 
13
13
  def copy_values(other_cache)
14
14
  # use the same cached values but still fall back to the correct pool
15
- [:@columns, :@columns_hash, :@primary_keys, :@data_sources].each do |iv|
15
+ %i[@columns @columns_hash @primary_keys @data_sources].each do |iv|
16
16
  instance_variable_set(iv, other_cache.instance_variable_get(iv))
17
17
  end
18
18
  end
@@ -7,7 +7,7 @@ module Switchman
7
7
  @shard_host = shard_host
8
8
  end
9
9
 
10
- def instrument(name, payload={})
10
+ def instrument(name, payload = {})
11
11
  shard = @shard_host&.shard
12
12
  # attribute_methods_generated? will be false during a reload -
13
13
  # when we might be doing a query while defining attribute methods,
@@ -3,12 +3,24 @@
3
3
  module Switchman
4
4
  module StandardError
5
5
  def initialize(*args)
6
- @active_shards = Shard.send(:active_shards).dup
6
+ # Shard.current can throw this when switchman isn't working right; if we try to
7
+ # do our stuff here, it'll cause a SystemStackError, which is a pain to deal with
8
+ if is_a?(::ActiveRecord::ConnectionNotEstablished)
9
+ super
10
+ return
11
+ end
12
+
13
+ if defined?(Shard)
14
+ @active_shards = Shard.sharded_models.map do |klass|
15
+ [klass, Shard.current(klass)]
16
+ end.compact.to_h
17
+ end
18
+
7
19
  super
8
20
  end
9
21
 
10
- def current_shard(category = :primary)
11
- @active_shards[category] || Shard.default
22
+ def current_shard(klass = ::ActiveRecord::Base)
23
+ @active_shards&.[](klass) || Shard.default
12
24
  end
13
25
  end
14
26
  end
@@ -11,19 +11,14 @@ module Switchman
11
11
  Shard.create!(default: true)
12
12
  rescue
13
13
  raise unless dont_create
14
+
14
15
  # database doesn't exist yet, presumably cause we're creating it right now
15
16
  return [nil, nil]
16
17
  end
17
18
  Shard.default(reload: true)
18
19
  end
19
20
 
20
- # can't auto-create a new shard on the default shard's db server if the
21
- # default shard is split across multiple db servers
22
- if ::ActiveRecord::Base.connection_handler.connection_pool_list.length > 1
23
- server1 = DatabaseServer.create(Shard.default.database_server.config)
24
- else
25
- server1 = Shard.default.database_server
26
- end
21
+ server1 = Shard.default.database_server
27
22
  server2 = DatabaseServer.create(Shard.default.database_server.config)
28
23
 
29
24
  if server1 == Shard.default.database_server && server1.config[:shard1] && server1.config[:shard2]
@@ -55,8 +50,8 @@ module Switchman
55
50
  shard1.destroy
56
51
  shard2.drop_database rescue nil
57
52
  shard2.destroy
58
- shard1 = server1.create_new_shard(:name => server1.config[:shard1])
59
- shard2 = server2.create_new_shard(:name => server1.config[:shard2])
53
+ shard1 = server1.create_new_shard(name: server1.config[:shard1])
54
+ shard2 = server2.create_new_shard(name: server1.config[:shard2])
60
55
  end
61
56
  [shard1, shard2]
62
57
  else
@@ -65,11 +60,12 @@ module Switchman
65
60
  end
66
61
 
67
62
  private
63
+
68
64
  def find_existing_test_shard(server, name)
69
65
  if server == Shard.default.database_server
70
66
  server.shards.where(name: name).first
71
67
  else
72
- 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
73
69
  # if somehow databases got created in a different order, change the shard to match
74
70
  shard.database_server = server if shard
75
71
  shard
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = "2.0.2"
4
+ VERSION = '3.0.0'
5
5
  end
@@ -1,20 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module Rake
3
5
  def self.filter_database_servers(&block)
4
6
  chain = filter_database_servers_chain # use a local variable so that the current chain is closed over in the following lambda
5
- @filter_database_servers_chain = lambda { |servers| block.call(servers, chain) }
7
+ @filter_database_servers_chain = ->(servers) { block.call(servers, chain) }
6
8
  end
7
9
 
8
10
  def self.scope(base_scope = Shard,
9
- database_server: ENV['DATABASE_SERVER'],
10
- shard: ENV['SHARD'])
11
+ database_server: ENV['DATABASE_SERVER'],
12
+ shard: ENV['SHARD'])
11
13
  servers = DatabaseServer.all
12
14
 
13
15
  if database_server
14
16
  servers = database_server
15
17
  if servers.first == '-'
16
18
  negative = true
17
- servers = servers[1..-1]
19
+ servers = servers[1..]
18
20
  end
19
21
  servers = servers.split(',')
20
22
  open = servers.delete('open')
@@ -31,16 +33,14 @@ module Switchman
31
33
 
32
34
  servers = filter_database_servers_chain.call(servers)
33
35
 
34
- scope = base_scope.order(::Arel.sql("database_server_id IS NOT NULL, database_server_id, id"))
36
+ scope = base_scope.order(::Arel.sql('database_server_id IS NOT NULL, database_server_id, id'))
35
37
  if servers != DatabaseServer.all
36
- conditions = ["database_server_id IN (?)", servers.map(&:id)]
37
- conditions.first << " OR database_server_id IS NULL" if servers.include?(Shard.default.database_server)
38
+ conditions = ['database_server_id IN (?)', servers.map(&:id)]
39
+ conditions.first << ' OR database_server_id IS NULL' if servers.include?(Shard.default.database_server)
38
40
  scope = scope.where(conditions)
39
41
  end
40
42
 
41
- if shard
42
- scope = shard_scope(scope, shard)
43
- end
43
+ scope = shard_scope(scope, shard) if shard
44
44
 
45
45
  scope
46
46
  end
@@ -49,11 +49,11 @@ module Switchman
49
49
  { parallel: ENV['PARALLEL'].to_i, max_procs: ENV['MAX_PARALLEL_PROCS'] }
50
50
  end
51
51
 
52
- # categories - an array or proc, to activate as the current shard during the
52
+ # classes - an array or proc, to activate as the current shard during the
53
53
  # task. tasks which modify the schema may want to pass all categories in
54
54
  # so that schema updates for non-default tables happen against all shards.
55
55
  # this is handled automatically for the default migration tasks, below.
56
- def self.shardify_task(task_name, categories: [:primary])
56
+ def self.shardify_task(task_name, classes: [::ActiveRecord::Base])
57
57
  old_task = ::Rake::Task[task_name]
58
58
  old_actions = old_task.actions.dup
59
59
  old_task.actions.clear
@@ -66,43 +66,30 @@ module Switchman
66
66
 
67
67
  ::GuardRail.activate(:deploy) do
68
68
  Shard.default.database_server.unguard do
69
- begin
70
- categories = categories.call if categories.respond_to?(:call)
71
- Shard.with_each_shard(scope, categories, options) do
72
- shard = Shard.current
73
- puts "#{shard.id}: #{shard.description}"
74
- ::ActiveRecord::Base.connection_pool.spec.config[:shard_name] = Shard.current.name
75
- if ::Rails.version < '6.0'
76
- ::ActiveRecord::Base.configurations[::Rails.env] = ::ActiveRecord::Base.connection_pool.spec.config.stringify_keys
77
- else
78
- # Adopted from the deprecated code that currently lives in rails proper
79
- remaining_configs = ::ActiveRecord::Base.configurations.configurations.reject { |db_config| db_config.env_name == ::Rails.env }
80
- new_config = ::ActiveRecord::DatabaseConfigurations.new(::Rails.env =>
81
- ::ActiveRecord::Base.connection_pool.spec.config.stringify_keys).configurations
82
- new_configs = remaining_configs + new_config
83
-
84
- ::ActiveRecord::Base.configurations = new_configs
85
- end
86
- shard.database_server.unguard do
87
- old_actions.each { |action| action.call(*task_args) }
88
- end
89
- nil
69
+ classes = classes.call if classes.respond_to?(:call)
70
+ Shard.with_each_shard(scope, classes, **options) do
71
+ shard = Shard.current
72
+ puts "#{shard.id}: #{shard.description}"
73
+
74
+ shard.database_server.unguard do
75
+ old_actions.each { |action| action.call(*task_args) }
90
76
  end
91
- rescue => e
92
- puts "Exception from #{e.current_shard.id}: #{e.current_shard.description}" if options[:parallel] != 0
93
- raise
77
+ nil
94
78
  end
79
+ rescue => e
80
+ puts "Exception from #{e.current_shard.id}: #{e.current_shard.description}" if options[:parallel] != 0
81
+ raise
82
+
83
+ #::ActiveRecord::Base.configurations = old_configurations
95
84
  end
96
85
  end
97
86
  end
98
87
  end
99
88
 
100
- %w{db:migrate db:migrate:up db:migrate:down db:rollback}.each do |task_name|
101
- shardify_task(task_name, categories: ->{ Shard.categories })
89
+ %w[db:migrate db:migrate:up db:migrate:down db:rollback].each do |task_name|
90
+ shardify_task(task_name, classes: -> { Shard.sharded_models })
102
91
  end
103
92
 
104
- private
105
-
106
93
  def self.shard_scope(scope, raw_shard_ids)
107
94
  raw_shard_ids = raw_shard_ids.split(',')
108
95
 
@@ -125,6 +112,7 @@ module Switchman
125
112
  when /^(-?)(\d+)?\.\.(\.)?(\d+)?$/
126
113
  negative, start, open, finish = $1.present?, $2, $3.present?, $4
127
114
  raise "Invalid shard id or range: #{id}" unless start || finish
115
+
128
116
  range = []
129
117
  range << "id>=#{start}" if start
130
118
  range << "id<#{'=' unless open}#{finish}" if finish
@@ -136,12 +124,12 @@ module Switchman
136
124
  when %r{^(-?\d+)/(\d+)$}
137
125
  numerator = $1.to_i
138
126
  denominator = $2.to_i
139
- if numerator == 0 || numerator.abs > denominator
140
- raise "Invalid fractional chunk: #{id}"
141
- end
127
+ raise "Invalid fractional chunk: #{id}" if numerator.zero? || numerator.abs > denominator
128
+
142
129
  # one chunk means everything
143
130
  if denominator == 1
144
131
  next if numerator == 1
132
+
145
133
  return scope.none
146
134
  end
147
135
 
@@ -156,24 +144,25 @@ module Switchman
156
144
  select = []
157
145
  if index != 1
158
146
  subscope = subscope.offset(per_chunk * (index - 1))
159
- select << "MIN(id) AS min_id"
147
+ select << 'MIN(id) AS min_id'
160
148
  end
161
149
  if index != denominator
162
150
  subscope = subscope.limit(per_chunk)
163
- select << "MAX(id) AS max_id"
164
- end
165
-
166
- result = Shard.from(subscope).select(select.join(", ")).to_a.first
167
- if index == 1
168
- range = "id<=#{result['max_id']}"
169
- elsif index == denominator
170
- range = "id>=#{result['min_id']}"
171
- else
172
- range = "(id>=#{result['min_id']} AND id<=#{result['max_id']})"
151
+ select << 'MAX(id) AS max_id'
173
152
  end
174
153
 
175
- (numerator < 0 ? negative_ranges : ranges) << range
176
- else
154
+ result = Shard.from(subscope).select(select.join(', ')).to_a.first
155
+ range = case index
156
+ when 1
157
+ "id<=#{result['max_id']}"
158
+ when denominator
159
+ "id>=#{result['min_id']}"
160
+ else
161
+ "(id>=#{result['min_id']} AND id<=#{result['max_id']})"
162
+ end
163
+
164
+ (numerator.negative? ? negative_ranges : ranges) << range
165
+ else
177
166
  raise "Invalid shard id or range: #{id}"
178
167
  end
179
168
  end
@@ -182,27 +171,24 @@ module Switchman
182
171
  negative_shard_ids.uniq!
183
172
  unless shard_ids.empty?
184
173
  shard_ids -= negative_shard_ids
185
- if shard_ids.empty? && ranges.empty?
186
- return scope.none
187
- end
174
+ return scope.none if shard_ids.empty? && ranges.empty?
175
+
188
176
  # we already trimmed them all out; no need to make the server do it as well
189
177
  negative_shard_ids = [] if ranges.empty?
190
178
  end
191
179
 
192
180
  conditions = []
193
181
  positive_queries = []
194
- unless ranges.empty?
195
- positive_queries << ranges.join(" OR ")
196
- end
182
+ positive_queries << ranges.join(' OR ') unless ranges.empty?
197
183
  unless shard_ids.empty?
198
- positive_queries << "id IN (?)"
184
+ positive_queries << 'id IN (?)'
199
185
  conditions << shard_ids
200
186
  end
201
- positive_query = positive_queries.join(" OR ")
187
+ positive_query = positive_queries.join(' OR ')
202
188
  scope = scope.where(positive_query, *conditions) unless positive_queries.empty?
203
189
 
204
- scope = scope.where("NOT (#{negative_ranges.join(" OR")})") unless negative_ranges.empty?
205
- scope = scope.where("id NOT IN (?)", negative_shard_ids) unless negative_shard_ids.empty?
190
+ scope = scope.where("NOT (#{negative_ranges.join(' OR')})") unless negative_ranges.empty?
191
+ scope = scope.where('id NOT IN (?)', negative_shard_ids) unless negative_shard_ids.empty?
206
192
  scope
207
193
  end
208
194
 
@@ -213,18 +199,17 @@ module Switchman
213
199
 
214
200
  module ActiveRecord
215
201
  module PostgreSQLDatabaseTasks
216
- def structure_dump(filename, extra_flags=nil)
202
+ def structure_dump(filename, extra_flags = nil)
217
203
  set_psql_env
218
204
  args = ['-s', '-x', '-O', '-f', filename]
219
205
  args.concat(Array(extra_flags)) if extra_flags
220
- search_path = configuration['schema_search_path']
221
206
  shard = Shard.current.name
222
207
  serialized_search_path = shard
223
208
  args << "--schema=#{Shellwords.escape(shard)}"
224
209
 
225
210
  args << configuration['database']
226
211
  run_cmd('pg_dump', args, 'dumping')
227
- File.open(filename, "a") { |f| f << "SET search_path TO #{serialized_search_path};\n\n" }
212
+ File.open(filename, 'a') { |f| f << "SET search_path TO #{serialized_search_path};\n\n" }
228
213
  end
229
214
  end
230
215
  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: 2.0.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -10,76 +10,76 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-11-06 00:00:00.000000000 Z
13
+ date: 2021-03-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: railties
16
+ name: activerecord
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '5.1'
21
+ version: '6.1'
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '6.1'
24
+ version: '6.2'
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: '5.1'
31
+ version: '6.1'
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '6.1'
34
+ version: '6.2'
35
35
  - !ruby/object:Gem::Dependency
36
- name: activerecord
36
+ name: guardrail
37
37
  requirement: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '5.1'
42
- - - "<"
39
+ - - "~>"
43
40
  - !ruby/object:Gem::Version
44
- version: '6.1'
41
+ version: 3.0.0
45
42
  type: :runtime
46
43
  prerelease: false
47
44
  version_requirements: !ruby/object:Gem::Requirement
48
45
  requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- version: '5.1'
52
- - - "<"
46
+ - - "~>"
53
47
  - !ruby/object:Gem::Version
54
- version: '6.1'
48
+ version: 3.0.0
55
49
  - !ruby/object:Gem::Dependency
56
- name: guardrail
50
+ name: open4
57
51
  requirement: !ruby/object:Gem::Requirement
58
52
  requirements:
59
53
  - - "~>"
60
54
  - !ruby/object:Gem::Version
61
- version: 2.0.0
55
+ version: 1.3.0
62
56
  type: :runtime
63
57
  prerelease: false
64
58
  version_requirements: !ruby/object:Gem::Requirement
65
59
  requirements:
66
60
  - - "~>"
67
61
  - !ruby/object:Gem::Version
68
- version: 2.0.0
62
+ version: 1.3.0
69
63
  - !ruby/object:Gem::Dependency
70
- name: open4
64
+ name: railties
71
65
  requirement: !ruby/object:Gem::Requirement
72
66
  requirements:
73
- - - "~>"
67
+ - - ">="
74
68
  - !ruby/object:Gem::Version
75
- version: 1.3.0
69
+ version: '6.1'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '6.2'
76
73
  type: :runtime
77
74
  prerelease: false
78
75
  version_requirements: !ruby/object:Gem::Requirement
79
76
  requirements:
80
- - - "~>"
77
+ - - ">="
81
78
  - !ruby/object:Gem::Version
82
- version: 1.3.0
79
+ version: '6.1'
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '6.2'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: appraisal
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
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'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: pry
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -123,61 +137,103 @@ dependencies:
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
- name: pg
140
+ name: rake
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
- version: '0'
145
+ version: '13.0'
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
- version: '0'
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'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: rspec-rails
141
169
  requirement: !ruby/object:Gem::Requirement
142
170
  requirements:
143
- - - '='
171
+ - - "~>"
144
172
  - !ruby/object:Gem::Version
145
- version: 3.5.2
173
+ version: '4.0'
146
174
  type: :development
147
175
  prerelease: false
148
176
  version_requirements: !ruby/object:Gem::Requirement
149
177
  requirements:
150
- - - '='
178
+ - - "~>"
151
179
  - !ruby/object:Gem::Version
152
- version: 3.5.2
180
+ version: '4.0'
153
181
  - !ruby/object:Gem::Dependency
154
- name: simplecov
182
+ name: rubocop
155
183
  requirement: !ruby/object:Gem::Requirement
156
184
  requirements:
157
185
  - - "~>"
158
186
  - !ruby/object:Gem::Version
159
- version: '0.15'
187
+ version: '1.10'
160
188
  type: :development
161
189
  prerelease: false
162
190
  version_requirements: !ruby/object:Gem::Requirement
163
191
  requirements:
164
192
  - - "~>"
165
193
  - !ruby/object:Gem::Version
166
- version: '0.15'
194
+ version: '1.10'
167
195
  - !ruby/object:Gem::Dependency
168
- name: rake
196
+ name: rubocop-rake
169
197
  requirement: !ruby/object:Gem::Requirement
170
198
  requirements:
171
199
  - - "~>"
172
200
  - !ruby/object:Gem::Version
173
- version: '12.0'
201
+ version: '0.5'
174
202
  type: :development
175
203
  prerelease: false
176
204
  version_requirements: !ruby/object:Gem::Requirement
177
205
  requirements:
178
206
  - - "~>"
179
207
  - !ruby/object:Gem::Version
180
- version: '12.0'
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
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '0.15'
181
237
  description: Sharding
182
238
  email:
183
239
  - cody@instructure.com
@@ -187,6 +243,7 @@ extra_rdoc_files: []
187
243
  files:
188
244
  - Rakefile
189
245
  - app/models/switchman/shard.rb
246
+ - app/models/switchman/unsharded_record.rb
190
247
  - db/migrate/20130328212039_create_switchman_shards.rb
191
248
  - db/migrate/20130328224244_create_default_shard.rb
192
249
  - db/migrate/20161206323434_add_back_default_string_limits_switchman.rb
@@ -199,10 +256,10 @@ files:
199
256
  - lib/switchman/active_record/association.rb
200
257
  - lib/switchman/active_record/attribute_methods.rb
201
258
  - lib/switchman/active_record/base.rb
202
- - lib/switchman/active_record/batches.rb
203
259
  - lib/switchman/active_record/calculations.rb
204
- - lib/switchman/active_record/connection_handler.rb
205
260
  - lib/switchman/active_record/connection_pool.rb
261
+ - lib/switchman/active_record/database_configurations.rb
262
+ - lib/switchman/active_record/database_configurations/database_config.rb
206
263
  - lib/switchman/active_record/finder_methods.rb
207
264
  - lib/switchman/active_record/log_subscriber.rb
208
265
  - lib/switchman/active_record/migration.rb
@@ -217,12 +274,11 @@ files:
217
274
  - lib/switchman/active_record/spawn_methods.rb
218
275
  - lib/switchman/active_record/statement_cache.rb
219
276
  - lib/switchman/active_record/table_definition.rb
277
+ - lib/switchman/active_record/tasks/database_tasks.rb
220
278
  - lib/switchman/active_record/type_caster.rb
221
- - lib/switchman/active_record/where_clause_factory.rb
222
279
  - lib/switchman/active_support/cache.rb
223
280
  - lib/switchman/arel.rb
224
281
  - lib/switchman/call_super.rb
225
- - lib/switchman/connection_pool_proxy.rb
226
282
  - lib/switchman/database_server.rb
227
283
  - lib/switchman/default_shard.rb
228
284
  - lib/switchman/engine.rb
@@ -251,7 +307,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
307
  requirements:
252
308
  - - ">="
253
309
  - !ruby/object:Gem::Version
254
- version: '2.5'
310
+ version: '2.6'
255
311
  required_rubygems_version: !ruby/object:Gem::Requirement
256
312
  requirements:
257
313
  - - ">="