switchman 2.0.2 → 3.0.0
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.
- checksums.yaml +4 -4
- data/Rakefile +10 -2
- data/app/models/switchman/shard.rb +234 -270
- data/app/models/switchman/unsharded_record.rb +7 -0
- data/db/migrate/20130328212039_create_switchman_shards.rb +1 -1
- data/db/migrate/20130328224244_create_default_shard.rb +5 -5
- data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +1 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
- data/db/migrate/20180828192111_add_timestamps_to_shards.rb +7 -5
- data/db/migrate/20190114212900_add_unique_name_indexes.rb +5 -3
- data/lib/switchman.rb +3 -3
- data/lib/switchman/action_controller/caching.rb +2 -2
- data/lib/switchman/active_record/abstract_adapter.rb +1 -0
- data/lib/switchman/active_record/association.rb +78 -85
- data/lib/switchman/active_record/attribute_methods.rb +58 -52
- data/lib/switchman/active_record/base.rb +58 -59
- data/lib/switchman/active_record/calculations.rb +73 -66
- data/lib/switchman/active_record/connection_pool.rb +14 -41
- data/lib/switchman/active_record/database_configurations.rb +34 -0
- data/lib/switchman/active_record/database_configurations/database_config.rb +13 -0
- data/lib/switchman/active_record/finder_methods.rb +11 -16
- data/lib/switchman/active_record/log_subscriber.rb +4 -8
- data/lib/switchman/active_record/migration.rb +6 -15
- data/lib/switchman/active_record/model_schema.rb +1 -1
- data/lib/switchman/active_record/persistence.rb +4 -6
- data/lib/switchman/active_record/postgresql_adapter.rb +42 -53
- data/lib/switchman/active_record/predicate_builder.rb +1 -1
- data/lib/switchman/active_record/query_cache.rb +18 -19
- data/lib/switchman/active_record/query_methods.rb +172 -181
- data/lib/switchman/active_record/reflection.rb +6 -10
- data/lib/switchman/active_record/relation.rb +27 -21
- data/lib/switchman/active_record/spawn_methods.rb +27 -29
- data/lib/switchman/active_record/statement_cache.rb +18 -35
- data/lib/switchman/active_record/tasks/database_tasks.rb +16 -0
- data/lib/switchman/active_support/cache.rb +3 -5
- data/lib/switchman/arel.rb +13 -8
- data/lib/switchman/database_server.rb +121 -142
- data/lib/switchman/default_shard.rb +52 -16
- data/lib/switchman/engine.rb +61 -57
- data/lib/switchman/environment.rb +4 -8
- data/lib/switchman/errors.rb +1 -0
- data/lib/switchman/guard_rail.rb +6 -19
- data/lib/switchman/guard_rail/relation.rb +5 -7
- data/lib/switchman/r_spec_helper.rb +29 -37
- data/lib/switchman/rails.rb +14 -12
- data/lib/switchman/schema_cache.rb +1 -1
- data/lib/switchman/sharded_instrumenter.rb +1 -1
- data/lib/switchman/standard_error.rb +15 -3
- data/lib/switchman/test_helper.rb +6 -10
- data/lib/switchman/version.rb +1 -1
- data/lib/tasks/switchman.rake +54 -69
- metadata +100 -44
- data/lib/switchman/active_record/batches.rb +0 -11
- data/lib/switchman/active_record/connection_handler.rb +0 -172
- data/lib/switchman/active_record/where_clause_factory.rb +0 -36
- data/lib/switchman/connection_pool_proxy.rb +0 -169
data/lib/switchman/rails.rb
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Switchman
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
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(
|
|
11
|
-
@active_shards[
|
|
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
|
-
|
|
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(:
|
|
59
|
-
shard2 = server2.create_new_shard(:
|
|
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(
|
|
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
|
data/lib/switchman/version.rb
CHANGED
data/lib/tasks/switchman.rake
CHANGED
|
@@ -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 =
|
|
7
|
+
@filter_database_servers_chain = ->(servers) { block.call(servers, chain) }
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
def self.scope(base_scope = Shard,
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
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(
|
|
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 = [
|
|
37
|
-
conditions.first <<
|
|
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
|
-
#
|
|
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,
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
Shard.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
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
|
|
101
|
-
shardify_task(task_name,
|
|
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
|
|
140
|
-
|
|
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 <<
|
|
147
|
+
select << 'MIN(id) AS min_id'
|
|
160
148
|
end
|
|
161
149
|
if index != denominator
|
|
162
150
|
subscope = subscope.limit(per_chunk)
|
|
163
|
-
select <<
|
|
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
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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 <<
|
|
184
|
+
positive_queries << 'id IN (?)'
|
|
199
185
|
conditions << shard_ids
|
|
200
186
|
end
|
|
201
|
-
positive_query = positive_queries.join(
|
|
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(
|
|
205
|
-
scope = scope.where(
|
|
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,
|
|
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:
|
|
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:
|
|
13
|
+
date: 2021-03-17 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
|
-
name:
|
|
16
|
+
name: activerecord
|
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
|
18
18
|
requirements:
|
|
19
19
|
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '
|
|
21
|
+
version: '6.1'
|
|
22
22
|
- - "<"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: '6.
|
|
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: '
|
|
31
|
+
version: '6.1'
|
|
32
32
|
- - "<"
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: '6.
|
|
34
|
+
version: '6.2'
|
|
35
35
|
- !ruby/object:Gem::Dependency
|
|
36
|
-
name:
|
|
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:
|
|
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:
|
|
48
|
+
version: 3.0.0
|
|
55
49
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
50
|
+
name: open4
|
|
57
51
|
requirement: !ruby/object:Gem::Requirement
|
|
58
52
|
requirements:
|
|
59
53
|
- - "~>"
|
|
60
54
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
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:
|
|
62
|
+
version: 1.3.0
|
|
69
63
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
64
|
+
name: railties
|
|
71
65
|
requirement: !ruby/object:Gem::Requirement
|
|
72
66
|
requirements:
|
|
73
|
-
- - "
|
|
67
|
+
- - ">="
|
|
74
68
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: 1
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
180
|
+
version: '4.0'
|
|
153
181
|
- !ruby/object:Gem::Dependency
|
|
154
|
-
name:
|
|
182
|
+
name: rubocop
|
|
155
183
|
requirement: !ruby/object:Gem::Requirement
|
|
156
184
|
requirements:
|
|
157
185
|
- - "~>"
|
|
158
186
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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.
|
|
310
|
+
version: '2.6'
|
|
255
311
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
312
|
requirements:
|
|
257
313
|
- - ">="
|