switchman 3.0.9 → 3.1.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 +1 -1
- data/lib/switchman/action_controller/caching.rb +2 -2
- data/lib/switchman/active_record/abstract_adapter.rb +2 -4
- data/lib/switchman/active_record/associations.rb +223 -0
- data/lib/switchman/active_record/attribute_methods.rb +144 -84
- data/lib/switchman/active_record/base.rb +71 -31
- data/lib/switchman/active_record/calculations.rb +11 -4
- data/lib/switchman/active_record/connection_pool.rb +2 -4
- data/lib/switchman/active_record/database_configurations.rb +18 -2
- data/lib/switchman/active_record/finder_methods.rb +2 -2
- data/lib/switchman/active_record/model_schema.rb +1 -1
- data/lib/switchman/active_record/persistence.rb +3 -5
- data/lib/switchman/active_record/postgresql_adapter.rb +1 -1
- data/lib/switchman/active_record/query_methods.rb +20 -11
- data/lib/switchman/active_record/reflection.rb +1 -1
- data/lib/switchman/active_record/relation.rb +15 -18
- data/lib/switchman/active_record/statement_cache.rb +2 -2
- data/lib/switchman/active_record/table_definition.rb +1 -1
- data/lib/switchman/active_support/cache.rb +16 -0
- data/lib/switchman/database_server.rb +26 -18
- data/lib/switchman/default_shard.rb +0 -2
- data/lib/switchman/engine.rb +63 -125
- data/lib/switchman/errors.rb +4 -2
- data/lib/switchman/guard_rail/relation.rb +6 -9
- data/lib/switchman/guard_rail.rb +5 -0
- data/lib/switchman/parallel.rb +68 -0
- data/lib/switchman/r_spec_helper.rb +3 -0
- data/lib/switchman/rails.rb +2 -5
- data/{app/models → lib}/switchman/shard.rb +28 -133
- data/lib/switchman/sharded_instrumenter.rb +1 -1
- data/lib/switchman/standard_error.rb +10 -11
- data/{app/models → lib}/switchman/unsharded_record.rb +1 -1
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +22 -2
- data/lib/tasks/switchman.rake +16 -9
- metadata +20 -20
- data/lib/switchman/active_record/association.rb +0 -206
- data/lib/switchman/open4.rb +0 -80
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'switchman/database_server'
|
|
4
|
-
require 'switchman/default_shard'
|
|
5
|
-
require 'switchman/environment'
|
|
6
|
-
require 'switchman/errors'
|
|
7
|
-
|
|
8
3
|
module Switchman
|
|
9
4
|
class Shard < UnshardedRecord
|
|
10
5
|
# ten trillion possible ids per shard. yup.
|
|
@@ -42,12 +37,9 @@ module Switchman
|
|
|
42
37
|
# Now find the actual record, if it exists
|
|
43
38
|
@default = begin
|
|
44
39
|
find_cached('default_shard') { Shard.where(default: true).take } || default
|
|
45
|
-
# If we are *super* early in boot, the connection pool won't exist; we don't want to fill in the default shard yet
|
|
46
|
-
# Otherwise, rescue the fake default if the table doesn't exist
|
|
47
40
|
rescue
|
|
48
|
-
|
|
41
|
+
default
|
|
49
42
|
end
|
|
50
|
-
return default unless @default
|
|
51
43
|
|
|
52
44
|
# make sure this is not erroneously cached
|
|
53
45
|
@default.database_server.remove_instance_variable(:@primary_shard) if @default.database_server.instance_variable_defined?(:@primary_shard)
|
|
@@ -125,8 +117,7 @@ module Switchman
|
|
|
125
117
|
# * +classes+ - an array of classes to activate
|
|
126
118
|
# parallel: - true/false to execute in parallel, or an integer of how many
|
|
127
119
|
# sub-processes. Note that parallel invocation currently uses
|
|
128
|
-
# forking
|
|
129
|
-
# results back
|
|
120
|
+
# forking.
|
|
130
121
|
# exception: - :ignore, :raise, :defer (wait until the end and raise the first
|
|
131
122
|
# error), or a proc
|
|
132
123
|
def with_each_shard(*args, parallel: false, exception: :raise, &block)
|
|
@@ -159,137 +150,47 @@ module Switchman
|
|
|
159
150
|
return if database_servers.count.zero?
|
|
160
151
|
|
|
161
152
|
scopes = database_servers.to_h do |server|
|
|
162
|
-
[server, server.shards
|
|
153
|
+
[server, scope.merge(server.shards)]
|
|
163
154
|
end
|
|
164
155
|
else
|
|
165
156
|
scopes = scope.group_by(&:database_server)
|
|
166
157
|
end
|
|
167
158
|
|
|
168
|
-
exception_pipes = []
|
|
169
|
-
pids = []
|
|
170
|
-
out_fds = []
|
|
171
|
-
err_fds = []
|
|
172
|
-
pid_to_name_map = {}
|
|
173
|
-
fd_to_name_map = {}
|
|
174
|
-
errors = []
|
|
175
|
-
|
|
176
|
-
wait_for_output = lambda do
|
|
177
|
-
ready, = IO.select(out_fds + err_fds)
|
|
178
|
-
ready.each do |fd|
|
|
179
|
-
if fd.eof?
|
|
180
|
-
fd.close
|
|
181
|
-
out_fds.delete(fd)
|
|
182
|
-
err_fds.delete(fd)
|
|
183
|
-
next
|
|
184
|
-
end
|
|
185
|
-
line = fd.readline
|
|
186
|
-
puts "#{fd_to_name_map[fd]}: #{line}"
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# only one process; don't bother forking
|
|
191
|
-
return with_each_shard(scopes.first.last, classes, exception: exception, &block) if scopes.length == 1
|
|
192
|
-
|
|
193
159
|
# clear connections prior to forking (no more queries will be executed in the parent,
|
|
194
160
|
# and we want them gone so that we don't accidentally use them post-fork doing something
|
|
195
161
|
# silly like dealloc'ing prepared statements)
|
|
196
162
|
::ActiveRecord::Base.clear_all_connections!
|
|
197
163
|
|
|
198
|
-
|
|
164
|
+
parent_process_name = `ps -ocommand= -p#{Process.pid}`.slice(/#{$0}.*/)
|
|
165
|
+
ret = ::Parallel.map(scopes, in_processes: scopes.length > 1 ? parallel : 0) do |server, subscope|
|
|
199
166
|
name = server.id
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
# was started)
|
|
209
|
-
# first, simplify the binary name by stripping directories,
|
|
210
|
-
# then truncate arguments as necessary
|
|
211
|
-
bin = File.basename($0) # Process.argv0 doesn't work on Ruby 2.5 (https://bugs.ruby-lang.org/issues/15887)
|
|
212
|
-
max_length = 128 - bin.length - name.length - 3
|
|
213
|
-
args = ARGV.join(' ')
|
|
214
|
-
args = args[0..max_length] if max_length >= 0
|
|
215
|
-
new_title = [bin, args, name].join(' ')
|
|
167
|
+
# rubocop:disable Style/GlobalStdStream
|
|
168
|
+
$stdout = Parallel::PrefixingIO.new(name, STDOUT)
|
|
169
|
+
$stderr = Parallel::PrefixingIO.new(name, STDERR)
|
|
170
|
+
# rubocop:enable Style/GlobalStdStream
|
|
171
|
+
begin
|
|
172
|
+
max_length = 128 - name.length - 3
|
|
173
|
+
short_parent_name = parent_process_name[0..max_length] if max_length >= 0
|
|
174
|
+
new_title = [short_parent_name, name].join(' ')
|
|
216
175
|
Process.setproctitle(new_title)
|
|
217
|
-
|
|
218
|
-
with_each_shard(subscope, classes, exception: exception, &block)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
dumped = Marshal.dump(e)
|
|
223
|
-
dumped = nil if dumped.length > 64 * 1024
|
|
224
|
-
rescue
|
|
225
|
-
dumped = nil
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
if dumped.nil?
|
|
229
|
-
# couldn't dump the exception; create a copy with just
|
|
230
|
-
# the message and the backtrace
|
|
231
|
-
e2 = e.class.new(e.message)
|
|
232
|
-
backtrace = e.backtrace
|
|
233
|
-
# truncate excessively long backtraces
|
|
234
|
-
backtrace = backtrace[0...25] + ['...'] + backtrace[-25..] if backtrace.length > 50
|
|
235
|
-
e2.set_backtrace(backtrace)
|
|
236
|
-
e2.instance_variable_set(:@active_shards, e.instance_variable_get(:@active_shards))
|
|
237
|
-
dumped = Marshal.dump(e2)
|
|
238
|
-
end
|
|
239
|
-
exception_pipe.last.set_encoding(dumped.encoding)
|
|
240
|
-
exception_pipe.last.write(dumped)
|
|
241
|
-
exception_pipe.last.flush
|
|
242
|
-
exception_pipe.last.close
|
|
243
|
-
exit! 1
|
|
244
|
-
end)
|
|
245
|
-
exception_pipe.last.close
|
|
246
|
-
pids << pid
|
|
247
|
-
io_in.close # don't care about writing to stdin
|
|
248
|
-
out_fds << io_out
|
|
249
|
-
err_fds << io_err
|
|
250
|
-
pid_to_name_map[pid] = name
|
|
251
|
-
fd_to_name_map[io_out] = name
|
|
252
|
-
fd_to_name_map[io_err] = name
|
|
253
|
-
|
|
254
|
-
while pids.count >= parallel
|
|
255
|
-
while out_fds.count >= parallel
|
|
256
|
-
# wait for output if we've hit the parallel limit
|
|
257
|
-
wait_for_output.call
|
|
258
|
-
end
|
|
259
|
-
# we've gotten all the output from one fd so wait for its child process to exit
|
|
260
|
-
found_pid, status = Process.wait2
|
|
261
|
-
pids.delete(found_pid)
|
|
262
|
-
errors << pid_to_name_map[found_pid] if status.exitstatus != 0
|
|
176
|
+
Switchman.config[:on_fork_proc]&.call
|
|
177
|
+
with_each_shard(subscope, classes, exception: exception, &block).map { |result| Parallel::ResultWrapper.new(result) }
|
|
178
|
+
rescue => e
|
|
179
|
+
logger.error e.full_message
|
|
180
|
+
Parallel::QuietExceptionWrapper.new(name, ::Parallel::ExceptionWrapper.new(e))
|
|
263
181
|
end
|
|
264
|
-
|
|
265
|
-
found_pid, status = Process.wait2
|
|
266
|
-
pids.delete(found_pid)
|
|
267
|
-
errors << pid_to_name_map[found_pid] if status.exitstatus != 0
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
wait_for_output.call while out_fds.any? || err_fds.any?
|
|
271
|
-
pids.each do |pid|
|
|
272
|
-
_, status = Process.waitpid2(pid)
|
|
273
|
-
errors << pid_to_name_map[pid] if status.exitstatus != 0
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
# check for an exception; we only re-raise the first one
|
|
277
|
-
exception_pipes.each do |exception_pipe|
|
|
278
|
-
serialized_exception = exception_pipe.first.read
|
|
279
|
-
next if serialized_exception.empty?
|
|
280
|
-
|
|
281
|
-
ex = Marshal.load(serialized_exception) # rubocop:disable Security/MarshalLoad
|
|
282
|
-
raise ex
|
|
283
|
-
ensure
|
|
284
|
-
exception_pipe.first.close
|
|
285
|
-
end
|
|
182
|
+
end.flatten
|
|
286
183
|
|
|
184
|
+
errors = ret.select { |val| val.is_a?(Parallel::QuietExceptionWrapper) }
|
|
287
185
|
unless errors.empty?
|
|
288
|
-
raise
|
|
289
|
-
|
|
186
|
+
raise errors.first.exception if errors.length == 1
|
|
187
|
+
|
|
188
|
+
raise Errors::ParallelShardExecError,
|
|
189
|
+
"The following database server(s) did not finish processing cleanly: #{errors.map(&:name).sort.join(', ')}",
|
|
190
|
+
cause: errors.first.exception
|
|
290
191
|
end
|
|
291
192
|
|
|
292
|
-
return
|
|
193
|
+
return ret.map(&:result)
|
|
293
194
|
end
|
|
294
195
|
|
|
295
196
|
classes ||= []
|
|
@@ -467,16 +368,12 @@ module Switchman
|
|
|
467
368
|
|
|
468
369
|
private
|
|
469
370
|
|
|
470
|
-
def sharding_initialized
|
|
471
|
-
@sharding_initialized ||= false
|
|
472
|
-
end
|
|
473
|
-
|
|
474
371
|
def add_sharded_model(klass)
|
|
475
372
|
@sharded_models = (sharded_models + [klass]).freeze
|
|
476
|
-
|
|
373
|
+
configure_connects_to
|
|
477
374
|
end
|
|
478
375
|
|
|
479
|
-
def
|
|
376
|
+
def configure_connects_to
|
|
480
377
|
full_connects_to_hash = DatabaseServer.all.to_h { |db| [db.id.to_sym, db.connects_to_hash] }
|
|
481
378
|
sharded_models.each do |klass|
|
|
482
379
|
connects_to_hash = full_connects_to_hash.deep_dup
|
|
@@ -498,8 +395,6 @@ module Switchman
|
|
|
498
395
|
|
|
499
396
|
klass.connects_to shards: connects_to_hash
|
|
500
397
|
end
|
|
501
|
-
|
|
502
|
-
@sharding_initialized = true
|
|
503
398
|
end
|
|
504
399
|
|
|
505
400
|
# in-process caching
|
|
@@ -16,7 +16,7 @@ module Switchman
|
|
|
16
16
|
payload[:shard] = {
|
|
17
17
|
database_server_id: shard.database_server.id,
|
|
18
18
|
id: shard.id,
|
|
19
|
-
env:
|
|
19
|
+
env: ::Rails.version < '7.0' ? @shard_host.pool.connection_klass&.current_role : @shard_host.pool.connection_class&.current_role
|
|
20
20
|
}
|
|
21
21
|
end
|
|
22
22
|
super name, payload
|
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
module Switchman
|
|
4
4
|
module StandardError
|
|
5
5
|
def initialize(*args)
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
if is_a?(::
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
end
|
|
6
|
+
super
|
|
7
|
+
# These seem to get themselves into a bad state if we try to lookup shards while processing
|
|
8
|
+
return if is_a?(IO::EAGAINWaitReadable)
|
|
9
|
+
|
|
10
|
+
return if Thread.current[:switchman_error_handler]
|
|
12
11
|
|
|
13
12
|
begin
|
|
14
|
-
|
|
15
|
-
rescue ::ActiveRecord::ConnectionNotEstablished
|
|
16
|
-
# If we hit an error really early in boot, activerecord may not be initialized yet
|
|
17
|
-
end
|
|
13
|
+
Thread.current[:switchman_error_handler] = true
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
@active_shards ||= Shard.active_shards
|
|
16
|
+
ensure
|
|
17
|
+
Thread.current[:switchman_error_handler] = nil
|
|
18
|
+
end
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def current_shard(klass = ::ActiveRecord::Base)
|
data/lib/switchman/version.rb
CHANGED
data/lib/switchman.rb
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'guard_rail'
|
|
4
|
-
require '
|
|
5
|
-
|
|
4
|
+
require 'zeitwerk'
|
|
5
|
+
|
|
6
|
+
class SwitchmanInflector < Zeitwerk::GemInflector
|
|
7
|
+
def camelize(basename, abspath)
|
|
8
|
+
if basename =~ /\Apostgresql_(.*)/
|
|
9
|
+
'PostgreSQL' + super($1, abspath)
|
|
10
|
+
else
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
loader = Zeitwerk::Loader.for_gem
|
|
17
|
+
loader.inflector = SwitchmanInflector.new(__FILE__)
|
|
18
|
+
loader.setup
|
|
6
19
|
|
|
7
20
|
module Switchman
|
|
8
21
|
def self.config
|
|
@@ -18,5 +31,12 @@ module Switchman
|
|
|
18
31
|
@cache = cache
|
|
19
32
|
end
|
|
20
33
|
|
|
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
|
|
36
|
+
end
|
|
37
|
+
|
|
21
38
|
class OrderOnMultiShardQuery < RuntimeError; end
|
|
22
39
|
end
|
|
40
|
+
|
|
41
|
+
# Load the engine and everything associated at gem load time
|
|
42
|
+
Switchman::Engine
|
data/lib/tasks/switchman.rake
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
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
|
+
|
|
3
14
|
module Switchman
|
|
4
15
|
module Rake
|
|
5
16
|
def self.filter_database_servers(&block)
|
|
@@ -35,9 +46,9 @@ module Switchman
|
|
|
35
46
|
|
|
36
47
|
scope = base_scope.order(::Arel.sql('database_server_id IS NOT NULL, database_server_id, id'))
|
|
37
48
|
if servers != DatabaseServer.all
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
scope = scope.where(
|
|
49
|
+
database_server_ids = servers.map(&:id)
|
|
50
|
+
database_server_ids << nil if servers.include?(Shard.default.database_server)
|
|
51
|
+
scope = scope.where(database_server_id: database_server_ids)
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
scope = shard_scope(scope, shard) if shard
|
|
@@ -50,9 +61,7 @@ module Switchman
|
|
|
50
61
|
end
|
|
51
62
|
|
|
52
63
|
# classes - an array or proc, to activate as the current shard during the
|
|
53
|
-
# task.
|
|
54
|
-
# so that schema updates for non-default tables happen against all shards.
|
|
55
|
-
# this is handled automatically for the default migration tasks, below.
|
|
64
|
+
# task.
|
|
56
65
|
def self.shardify_task(task_name, classes: [::ActiveRecord::Base])
|
|
57
66
|
old_task = ::Rake::Task[task_name]
|
|
58
67
|
old_actions = old_task.actions.dup
|
|
@@ -77,10 +86,8 @@ module Switchman
|
|
|
77
86
|
nil
|
|
78
87
|
end
|
|
79
88
|
rescue => e
|
|
80
|
-
|
|
89
|
+
warn "Exception from #{e.current_shard.id}: #{e.current_shard.description}:\n#{e.full_message}" if options[:parallel] != 0
|
|
81
90
|
raise
|
|
82
|
-
|
|
83
|
-
# ::ActiveRecord::Base.configurations = old_configurations
|
|
84
91
|
end
|
|
85
92
|
end
|
|
86
93
|
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.0
|
|
4
|
+
version: 3.1.0
|
|
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: 2022-
|
|
13
|
+
date: 2022-06-02 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: activerecord
|
|
@@ -21,7 +21,7 @@ dependencies:
|
|
|
21
21
|
version: 6.1.4
|
|
22
22
|
- - "<"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: '
|
|
24
|
+
version: '7.1'
|
|
25
25
|
type: :runtime
|
|
26
26
|
prerelease: false
|
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -31,35 +31,35 @@ dependencies:
|
|
|
31
31
|
version: 6.1.4
|
|
32
32
|
- - "<"
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: '
|
|
34
|
+
version: '7.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.
|
|
41
|
+
version: 3.0.1
|
|
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.
|
|
48
|
+
version: 3.0.1
|
|
49
49
|
- !ruby/object:Gem::Dependency
|
|
50
|
-
name:
|
|
50
|
+
name: parallel
|
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
|
52
52
|
requirements:
|
|
53
53
|
- - "~>"
|
|
54
54
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: 1.
|
|
55
|
+
version: '1.22'
|
|
56
56
|
type: :runtime
|
|
57
57
|
prerelease: false
|
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
|
59
59
|
requirements:
|
|
60
60
|
- - "~>"
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: 1.
|
|
62
|
+
version: '1.22'
|
|
63
63
|
- !ruby/object:Gem::Dependency
|
|
64
64
|
name: railties
|
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -69,7 +69,7 @@ dependencies:
|
|
|
69
69
|
version: '6.1'
|
|
70
70
|
- - "<"
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: '
|
|
72
|
+
version: '7.1'
|
|
73
73
|
type: :runtime
|
|
74
74
|
prerelease: false
|
|
75
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -79,7 +79,7 @@ dependencies:
|
|
|
79
79
|
version: '6.1'
|
|
80
80
|
- - "<"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
82
|
+
version: '7.1'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: appraisal
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -242,8 +242,6 @@ extensions: []
|
|
|
242
242
|
extra_rdoc_files: []
|
|
243
243
|
files:
|
|
244
244
|
- Rakefile
|
|
245
|
-
- app/models/switchman/shard.rb
|
|
246
|
-
- app/models/switchman/unsharded_record.rb
|
|
247
245
|
- db/migrate/20130328212039_create_switchman_shards.rb
|
|
248
246
|
- db/migrate/20130328224244_create_default_shard.rb
|
|
249
247
|
- db/migrate/20161206323434_add_back_default_string_limits_switchman.rb
|
|
@@ -253,7 +251,7 @@ files:
|
|
|
253
251
|
- lib/switchman.rb
|
|
254
252
|
- lib/switchman/action_controller/caching.rb
|
|
255
253
|
- lib/switchman/active_record/abstract_adapter.rb
|
|
256
|
-
- lib/switchman/active_record/
|
|
254
|
+
- lib/switchman/active_record/associations.rb
|
|
257
255
|
- lib/switchman/active_record/attribute_methods.rb
|
|
258
256
|
- lib/switchman/active_record/base.rb
|
|
259
257
|
- lib/switchman/active_record/calculations.rb
|
|
@@ -287,12 +285,14 @@ files:
|
|
|
287
285
|
- lib/switchman/errors.rb
|
|
288
286
|
- lib/switchman/guard_rail.rb
|
|
289
287
|
- lib/switchman/guard_rail/relation.rb
|
|
290
|
-
- lib/switchman/
|
|
288
|
+
- lib/switchman/parallel.rb
|
|
291
289
|
- lib/switchman/r_spec_helper.rb
|
|
292
290
|
- lib/switchman/rails.rb
|
|
291
|
+
- lib/switchman/shard.rb
|
|
293
292
|
- lib/switchman/sharded_instrumenter.rb
|
|
294
293
|
- lib/switchman/standard_error.rb
|
|
295
294
|
- lib/switchman/test_helper.rb
|
|
295
|
+
- lib/switchman/unsharded_record.rb
|
|
296
296
|
- lib/switchman/version.rb
|
|
297
297
|
- lib/tasks/switchman.rake
|
|
298
298
|
homepage: http://www.instructure.com/
|
|
@@ -300,7 +300,7 @@ licenses:
|
|
|
300
300
|
- MIT
|
|
301
301
|
metadata:
|
|
302
302
|
rubygems_mfa_required: 'true'
|
|
303
|
-
post_install_message:
|
|
303
|
+
post_install_message:
|
|
304
304
|
rdoc_options: []
|
|
305
305
|
require_paths:
|
|
306
306
|
- lib
|
|
@@ -308,15 +308,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
308
308
|
requirements:
|
|
309
309
|
- - ">="
|
|
310
310
|
- !ruby/object:Gem::Version
|
|
311
|
-
version: '2.
|
|
311
|
+
version: '2.7'
|
|
312
312
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
313
313
|
requirements:
|
|
314
314
|
- - ">="
|
|
315
315
|
- !ruby/object:Gem::Version
|
|
316
316
|
version: '0'
|
|
317
317
|
requirements: []
|
|
318
|
-
rubygems_version: 3.1.
|
|
319
|
-
signing_key:
|
|
318
|
+
rubygems_version: 3.1.6
|
|
319
|
+
signing_key:
|
|
320
320
|
specification_version: 4
|
|
321
321
|
summary: Rails sharding magic
|
|
322
322
|
test_files: []
|