switchman 3.5.13 → 3.5.14
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/lib/switchman/active_record/base.rb +6 -1
- data/lib/switchman/database_server.rb +31 -0
- data/lib/switchman/default_shard.rb +11 -0
- data/lib/switchman/r_spec_helper.rb +1 -1
- data/lib/switchman/shard.rb +51 -1
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +21 -17
- data/lib/tasks/switchman.rake +14 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 243c4f20483016069c4c18efd47a64a8b2078596f254c1152f4f2a70555054f0
|
4
|
+
data.tar.gz: 332d8e5a2d5e119d1599e259f27fa1ba25e9f3139cc7504bd159aebcb730e724
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53604b1eedb8bd5ca453d617eb7e4c83ad5080bad4ccb2dff0cced4be2baaeccbe139d7b5936face689e2ccbd94cac338d39f7ecf2ace8a25f61f81fe47ed0c8
|
7
|
+
data.tar.gz: 5f9b8523159c6eeec8275838a825c9c911ad136ef33d32d362e80ce63008f130e7789f1863b851d9527c68591bcbcfa6aa95183f2b6cca5eef7e55096194abb4
|
@@ -57,7 +57,12 @@ module Switchman
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def clear_query_caches_for_current_thread
|
60
|
-
::
|
60
|
+
pools = if ::Rails.version < "7.1"
|
61
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list
|
62
|
+
else
|
63
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list(:all)
|
64
|
+
end
|
65
|
+
pools.each do |pool|
|
61
66
|
pool.connection(switch_shard: false).clear_query_cache if pool.active_connection?
|
62
67
|
end
|
63
68
|
end
|
@@ -10,6 +10,10 @@ module Switchman
|
|
10
10
|
attr_accessor :creating_new_shard
|
11
11
|
attr_reader :all_roles
|
12
12
|
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
delegate :each, to: :all
|
16
|
+
|
13
17
|
def all
|
14
18
|
database_servers.values
|
15
19
|
end
|
@@ -50,6 +54,10 @@ module Switchman
|
|
50
54
|
all.each { |db| db.guard! if db.config[:prefer_secondary] }
|
51
55
|
end
|
52
56
|
|
57
|
+
def regions
|
58
|
+
@regions ||= all.filter_map(&:region).uniq.sort
|
59
|
+
end
|
60
|
+
|
53
61
|
private
|
54
62
|
|
55
63
|
def reference_role(role)
|
@@ -140,6 +148,29 @@ module Switchman
|
|
140
148
|
end
|
141
149
|
end
|
142
150
|
|
151
|
+
def region
|
152
|
+
config[:region]
|
153
|
+
end
|
154
|
+
|
155
|
+
# @param region [String, Array<String>] the region(s) to check against
|
156
|
+
# @return true if the database server doesn't have a region, or it
|
157
|
+
# matches the specified region
|
158
|
+
def in_region?(region)
|
159
|
+
!self.region || (region.is_a?(Array) ? region.include?(self.region) : self.region == region)
|
160
|
+
end
|
161
|
+
|
162
|
+
# @return true if the database server doesn't have a region, Switchman is
|
163
|
+
# not configured with a region, or the database server's region matches
|
164
|
+
# Switchman's current region
|
165
|
+
def in_current_region?
|
166
|
+
unless instance_variable_defined?(:@in_current_region)
|
167
|
+
@in_current_region = !region ||
|
168
|
+
!Switchman.region ||
|
169
|
+
region == Switchman.region
|
170
|
+
end
|
171
|
+
@in_current_region
|
172
|
+
end
|
173
|
+
|
143
174
|
# locks this db to a specific environment, except for
|
144
175
|
# when doing writes (then it falls back to the current
|
145
176
|
# value of GuardRail.environment)
|
@@ -6,6 +6,7 @@ module Switchman
|
|
6
6
|
"default"
|
7
7
|
end
|
8
8
|
alias_method :cache_key, :id
|
9
|
+
|
9
10
|
def activate(*_classes)
|
10
11
|
yield
|
11
12
|
end
|
@@ -57,6 +58,16 @@ module Switchman
|
|
57
58
|
self
|
58
59
|
end
|
59
60
|
|
61
|
+
def region; end
|
62
|
+
|
63
|
+
def in_region?(_region)
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def in_current_region?
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
60
71
|
def _dump(_depth)
|
61
72
|
""
|
62
73
|
end
|
@@ -121,7 +121,7 @@ module Switchman
|
|
121
121
|
next if @@sharding_failed
|
122
122
|
|
123
123
|
# clean up after specs
|
124
|
-
DatabaseServer.
|
124
|
+
DatabaseServer.each do |ds|
|
125
125
|
if ds.fake? && ds != @shard2.database_server
|
126
126
|
ds.shards.delete_all unless use_transactional_tests
|
127
127
|
ds.destroy
|
data/lib/switchman/shard.rb
CHANGED
@@ -13,6 +13,47 @@ module Switchman
|
|
13
13
|
|
14
14
|
scope :primary, -> { where(name: nil).order(:database_server_id, :id).distinct_on(:database_server_id) }
|
15
15
|
|
16
|
+
scope :in_region, (lambda do |region, include_regionless: true|
|
17
|
+
next in_current_region if region.nil?
|
18
|
+
|
19
|
+
dbs_by_region = DatabaseServer.group_by(&:region)
|
20
|
+
db_count_in_this_region = dbs_by_region[region]&.length.to_i
|
21
|
+
db_count_in_this_region += dbs_by_region[nil]&.length.to_i if include_regionless
|
22
|
+
non_existent_database_servers = Shard.send(:non_existent_database_servers)
|
23
|
+
db_count_in_other_regions = DatabaseServer.all.length -
|
24
|
+
db_count_in_this_region +
|
25
|
+
non_existent_database_servers.length
|
26
|
+
|
27
|
+
dbs_in_this_region = dbs_by_region[region]&.map(&:id) || []
|
28
|
+
dbs_in_this_region += dbs_by_region[nil]&.map(&:id) || [] if include_regionless
|
29
|
+
|
30
|
+
if db_count_in_this_region <= db_count_in_other_regions
|
31
|
+
if dbs_in_this_region.include?(Shard.default.database_server.id)
|
32
|
+
where("database_server_id IN (?) OR database_server_id IS NULL", dbs_in_this_region)
|
33
|
+
else
|
34
|
+
where(database_server_id: dbs_in_this_region)
|
35
|
+
end
|
36
|
+
elsif db_count_in_other_regions.zero?
|
37
|
+
all
|
38
|
+
else
|
39
|
+
dbs_not_in_this_region = DatabaseServer.map(&:id) - dbs_in_this_region + non_existent_database_servers
|
40
|
+
if dbs_in_this_region.include?(Shard.default.database_server.id)
|
41
|
+
where("database_server_id NOT IN (?) OR database_server_id IS NULL", dbs_not_in_this_region)
|
42
|
+
else
|
43
|
+
where.not(database_server_id: dbs_not_in_this_region)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end)
|
47
|
+
|
48
|
+
scope :in_current_region, (lambda do |include_regionless: true|
|
49
|
+
# sharding isn't set up? maybe we're in tests, or a somehow degraded environment
|
50
|
+
# either way there's only one shard, and we always want to see it
|
51
|
+
return [default] unless default.is_a?(Switchman::Shard)
|
52
|
+
return all if !Switchman.region || DatabaseServer.none?(&:region)
|
53
|
+
|
54
|
+
in_region(Switchman.region, include_regionless: include_regionless)
|
55
|
+
end)
|
56
|
+
|
16
57
|
class << self
|
17
58
|
def sharded_models
|
18
59
|
@sharded_models ||= [::ActiveRecord::Base, UnshardedRecord].freeze
|
@@ -395,7 +436,7 @@ module Switchman
|
|
395
436
|
end
|
396
437
|
|
397
438
|
def configure_connects_to
|
398
|
-
full_connects_to_hash = DatabaseServer.
|
439
|
+
full_connects_to_hash = DatabaseServer.to_h { |db| [db.id.to_sym, db.connects_to_hash] }
|
399
440
|
sharded_models.each do |klass|
|
400
441
|
connects_to_hash = full_connects_to_hash.deep_dup
|
401
442
|
if klass == UnshardedRecord
|
@@ -484,8 +525,17 @@ module Switchman
|
|
484
525
|
argv[0] = File.basename(argv[0])
|
485
526
|
argv.shelljoin
|
486
527
|
end
|
528
|
+
|
529
|
+
# @return [Array<String>] the list of database servers that are in the
|
530
|
+
# config, but don't have any shards on them
|
531
|
+
def non_existent_database_servers
|
532
|
+
@non_existent_database_servers ||=
|
533
|
+
Shard.distinct.pluck(:database_server_id).compact - DatabaseServer.all.map(&:id)
|
534
|
+
end
|
487
535
|
end
|
488
536
|
|
537
|
+
delegate :region, :in_region?, :in_current_region?, to: :database_server
|
538
|
+
|
489
539
|
def name
|
490
540
|
unless instance_variable_defined?(:@name)
|
491
541
|
# protect against re-entrancy
|
data/lib/switchman/version.rb
CHANGED
data/lib/switchman.rb
CHANGED
@@ -20,27 +20,31 @@ loader.setup
|
|
20
20
|
module Switchman
|
21
21
|
Deprecation = ::ActiveSupport::Deprecation.new("4.0", "Switchman")
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
@config ||= {}
|
26
|
-
end
|
23
|
+
class << self
|
24
|
+
attr_writer :cache
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
def config
|
27
|
+
# TODO: load from yaml
|
28
|
+
@config ||= {}
|
29
|
+
end
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
def cache
|
32
|
+
(@cache.respond_to?(:call) ? @cache.call : @cache) || ::Rails.cache
|
33
|
+
end
|
34
|
+
|
35
|
+
def region
|
36
|
+
config[:region]
|
37
|
+
end
|
35
38
|
|
36
|
-
|
37
|
-
|
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
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
44
48
|
end
|
45
49
|
|
46
50
|
class OrderOnMultiShardQuery < RuntimeError; end
|
data/lib/tasks/switchman.rake
CHANGED
@@ -35,7 +35,7 @@ module Switchman
|
|
35
35
|
|
36
36
|
servers = servers.filter_map { |server| DatabaseServer.find(server) }
|
37
37
|
if open
|
38
|
-
open_servers = DatabaseServer.
|
38
|
+
open_servers = DatabaseServer.select { |server| server.config[:open] }
|
39
39
|
servers.concat(open_servers)
|
40
40
|
servers << DatabaseServer.find(nil) if open_servers.empty?
|
41
41
|
servers.uniq!
|
@@ -43,6 +43,19 @@ module Switchman
|
|
43
43
|
servers = DatabaseServer.all - servers if negative
|
44
44
|
end
|
45
45
|
|
46
|
+
ENV["REGION"]&.split(",")&.each do |region|
|
47
|
+
method = :select!
|
48
|
+
if region[0] == "-"
|
49
|
+
method = :reject!
|
50
|
+
region = region[1..]
|
51
|
+
end
|
52
|
+
if region == "self"
|
53
|
+
servers.send(method, &:in_current_region?)
|
54
|
+
else
|
55
|
+
servers.send(method) { |server| server.in_region?(region) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
46
59
|
servers = filter_database_servers_chain.call(servers)
|
47
60
|
|
48
61
|
scope = base_scope.order(::Arel.sql("database_server_id IS NOT NULL, database_server_id, id"))
|
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: 3.5.
|
4
|
+
version: 3.5.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-10-
|
13
|
+
date: 2023-10-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|