switchman 2.0.9 → 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 -271
- 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 +2 -2
- 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 -89
- 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 -47
- 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 +124 -164
- 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 -9
- data/lib/switchman/sharded_instrumenter.rb +1 -1
- data/lib/switchman/standard_error.rb +15 -3
- data/lib/switchman/test_helper.rb +7 -11
- data/lib/switchman/version.rb +1 -1
- data/lib/tasks/switchman.rake +54 -69
- metadata +87 -45
- 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 -173
@@ -4,17 +4,44 @@ require 'switchman/database_server'
|
|
4
4
|
|
5
5
|
module Switchman
|
6
6
|
class DefaultShard
|
7
|
-
def id
|
7
|
+
def id
|
8
|
+
'default'
|
9
|
+
end
|
8
10
|
alias cache_key id
|
9
|
-
def activate(*
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def
|
14
|
-
|
15
|
-
def
|
16
|
-
|
17
|
-
|
11
|
+
def activate(*_classes)
|
12
|
+
yield
|
13
|
+
end
|
14
|
+
|
15
|
+
def activate!(*classes); end
|
16
|
+
|
17
|
+
def default?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def primary?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def relative_id_for(local_id, _target = nil)
|
26
|
+
local_id
|
27
|
+
end
|
28
|
+
|
29
|
+
def global_id_for(local_id)
|
30
|
+
local_id
|
31
|
+
end
|
32
|
+
|
33
|
+
def database_server_id
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def database_server
|
38
|
+
DatabaseServer.find(nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_record?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
18
45
|
def name
|
19
46
|
unless instance_variable_defined?(:@name)
|
20
47
|
@name = nil # prevent taking this branch on recursion
|
@@ -22,18 +49,27 @@ module Switchman
|
|
22
49
|
end
|
23
50
|
@name
|
24
51
|
end
|
25
|
-
|
52
|
+
|
53
|
+
def description
|
54
|
+
::Rails.env
|
55
|
+
end
|
56
|
+
|
26
57
|
# The default's shard is always the default shard
|
27
|
-
def shard
|
28
|
-
|
58
|
+
def shard
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def _dump(_depth)
|
29
63
|
''
|
30
64
|
end
|
31
|
-
|
65
|
+
|
66
|
+
def self._load(_str)
|
32
67
|
Shard.default
|
33
68
|
end
|
34
69
|
|
35
|
-
def ==(
|
36
|
-
return true if
|
70
|
+
def ==(other)
|
71
|
+
return true if other.is_a?(DefaultShard) || (other.is_a?(Shard) && other[:default])
|
72
|
+
|
37
73
|
super
|
38
74
|
end
|
39
75
|
|
data/lib/switchman/engine.rb
CHANGED
@@ -4,24 +4,30 @@ module Switchman
|
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace Switchman
|
6
6
|
|
7
|
-
|
7
|
+
# enable Rails 6.1 style connection handling
|
8
|
+
config.active_record.legacy_connection_handling = false
|
9
|
+
config.active_record.writing_role = :primary
|
10
|
+
|
11
|
+
config.autoload_once_paths << File.expand_path('app/models', config.paths.path)
|
8
12
|
|
9
13
|
def self.lookup_stores(cache_store_config)
|
10
14
|
result = {}
|
11
15
|
cache_store_config.each do |key, value|
|
12
16
|
next if value.is_a?(String)
|
17
|
+
|
13
18
|
result[key] = ::ActiveSupport::Cache.lookup_store(value)
|
14
19
|
end
|
15
20
|
|
16
|
-
cache_store_config.each do |key, value|
|
21
|
+
cache_store_config.each do |key, value| # rubocop:disable Style/CombinableLoops
|
17
22
|
next unless value.is_a?(String)
|
23
|
+
|
18
24
|
result[key] = result[value]
|
19
25
|
end
|
20
26
|
result
|
21
27
|
end
|
22
28
|
|
23
|
-
initializer 'switchman.initialize_cache', :
|
24
|
-
require
|
29
|
+
initializer 'switchman.initialize_cache', before: 'initialize_cache' do
|
30
|
+
require 'switchman/active_support/cache'
|
25
31
|
::ActiveSupport::Cache.singleton_class.prepend(ActiveSupport::Cache::ClassMethods)
|
26
32
|
|
27
33
|
# if we haven't already setup our cache map out-of-band, set it up from
|
@@ -31,9 +37,7 @@ module Switchman
|
|
31
37
|
# to fill just the Rails.env entry in the cache map.
|
32
38
|
unless Switchman.config[:cache_map].present?
|
33
39
|
cache_store_config = ::Rails.configuration.cache_store
|
34
|
-
unless cache_store_config.is_a?(Hash)
|
35
|
-
cache_store_config = {::Rails.env => cache_store_config}
|
36
|
-
end
|
40
|
+
cache_store_config = { ::Rails.env => cache_store_config } unless cache_store_config.is_a?(Hash)
|
37
41
|
|
38
42
|
Switchman.config[:cache_map] = Engine.lookup_stores(cache_store_config)
|
39
43
|
end
|
@@ -42,7 +46,7 @@ module Switchman
|
|
42
46
|
# config.cache_store) didn't have an entry for Rails.env, add one using
|
43
47
|
# lookup_store(nil); matches the behavior of Rails' default
|
44
48
|
# initialize_cache initializer when config.cache_store is nil.
|
45
|
-
unless Switchman.config[:cache_map].
|
49
|
+
unless Switchman.config[:cache_map].key?(::Rails.env)
|
46
50
|
value = ::ActiveSupport::Cache.lookup_store(nil)
|
47
51
|
Switchman.config[:cache_map][::Rails.env] = value
|
48
52
|
end
|
@@ -51,7 +55,7 @@ module Switchman
|
|
51
55
|
store.middleware if store.respond_to?(:middleware)
|
52
56
|
end.compact.uniq
|
53
57
|
middlewares.each do |middleware|
|
54
|
-
config.middleware.insert_before(
|
58
|
+
config.middleware.insert_before('Rack::Runtime', middleware)
|
55
59
|
end
|
56
60
|
|
57
61
|
# prevent :initialize_cache from trying to (or needing to) set
|
@@ -62,39 +66,41 @@ module Switchman
|
|
62
66
|
::Rails.cache = Switchman.config[:cache_map][::Rails.env]
|
63
67
|
end
|
64
68
|
|
65
|
-
initializer 'switchman.extend_ar', :
|
69
|
+
initializer 'switchman.extend_ar', before: 'active_record.initialize_database' do
|
66
70
|
::ActiveSupport.on_load(:active_record) do
|
67
|
-
require
|
68
|
-
require
|
69
|
-
require
|
70
|
-
require
|
71
|
-
require
|
72
|
-
require
|
73
|
-
require
|
74
|
-
require
|
75
|
-
require
|
76
|
-
require
|
77
|
-
require
|
78
|
-
require
|
79
|
-
require
|
80
|
-
require
|
81
|
-
require
|
82
|
-
require
|
83
|
-
require
|
84
|
-
require
|
85
|
-
require
|
86
|
-
require
|
87
|
-
require
|
88
|
-
require
|
89
|
-
require
|
90
|
-
require
|
91
|
-
require
|
92
|
-
require
|
93
|
-
|
94
|
-
require "switchman/standard_error"
|
71
|
+
require 'switchman/active_record/abstract_adapter'
|
72
|
+
require 'switchman/active_record/association'
|
73
|
+
require 'switchman/active_record/attribute_methods'
|
74
|
+
require 'switchman/active_record/base'
|
75
|
+
require 'switchman/active_record/calculations'
|
76
|
+
require 'switchman/active_record/connection_pool'
|
77
|
+
require 'switchman/active_record/database_configurations'
|
78
|
+
require 'switchman/active_record/database_configurations/database_config'
|
79
|
+
require 'switchman/active_record/finder_methods'
|
80
|
+
require 'switchman/active_record/log_subscriber'
|
81
|
+
require 'switchman/active_record/migration'
|
82
|
+
require 'switchman/active_record/model_schema'
|
83
|
+
require 'switchman/active_record/persistence'
|
84
|
+
require 'switchman/active_record/predicate_builder'
|
85
|
+
require 'switchman/active_record/query_cache'
|
86
|
+
require 'switchman/active_record/query_methods'
|
87
|
+
require 'switchman/active_record/reflection'
|
88
|
+
require 'switchman/active_record/relation'
|
89
|
+
require 'switchman/active_record/spawn_methods'
|
90
|
+
require 'switchman/active_record/statement_cache'
|
91
|
+
require 'switchman/active_record/tasks/database_tasks'
|
92
|
+
require 'switchman/active_record/type_caster'
|
93
|
+
require 'switchman/arel'
|
94
|
+
require 'switchman/call_super'
|
95
|
+
require 'switchman/rails'
|
96
|
+
require 'switchman/guard_rail/relation'
|
97
|
+
require 'switchman/standard_error'
|
95
98
|
|
96
99
|
::StandardError.include(StandardError)
|
97
100
|
|
101
|
+
self.default_shard = ::Rails.env.to_sym
|
102
|
+
self.default_role = :primary
|
103
|
+
|
98
104
|
include ActiveRecord::Base
|
99
105
|
include ActiveRecord::AttributeMethods
|
100
106
|
include ActiveRecord::Persistence
|
@@ -106,6 +112,8 @@ module Switchman
|
|
106
112
|
::ActiveRecord::StatementCache::Substitute.send(:attr_accessor, :primary, :sharded)
|
107
113
|
|
108
114
|
::ActiveRecord::Associations::CollectionAssociation.prepend(ActiveRecord::CollectionAssociation)
|
115
|
+
::ActiveRecord::Associations::HasOneAssociation.prepend(ActiveRecord::ForeignAssociation)
|
116
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(ActiveRecord::ForeignAssociation)
|
109
117
|
|
110
118
|
::ActiveRecord::PredicateBuilder.singleton_class.prepend(ActiveRecord::PredicateBuilder)
|
111
119
|
|
@@ -117,21 +125,22 @@ module Switchman
|
|
117
125
|
|
118
126
|
::ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecord::Preloader::Association)
|
119
127
|
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::AbstractAdapter)
|
120
|
-
::ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ActiveRecord::ConnectionHandler)
|
121
128
|
::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecord::ConnectionPool)
|
122
129
|
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::QueryCache)
|
123
130
|
|
131
|
+
::ActiveRecord::DatabaseConfigurations.prepend(ActiveRecord::DatabaseConfigurations)
|
132
|
+
::ActiveRecord::DatabaseConfigurations::DatabaseConfig.prepend(ActiveRecord::DatabaseConfigurations::DatabaseConfig)
|
133
|
+
|
124
134
|
::ActiveRecord::LogSubscriber.prepend(ActiveRecord::LogSubscriber)
|
125
135
|
::ActiveRecord::Migration.prepend(ActiveRecord::Migration)
|
126
136
|
::ActiveRecord::Migration::Compatibility::V5_0.prepend(ActiveRecord::Migration::Compatibility::V5_0)
|
127
|
-
::ActiveRecord::MigrationContext.prepend(ActiveRecord::MigrationContext)
|
137
|
+
::ActiveRecord::MigrationContext.prepend(ActiveRecord::MigrationContext)
|
128
138
|
::ActiveRecord::Migrator.prepend(ActiveRecord::Migrator)
|
129
139
|
|
130
140
|
::ActiveRecord::Reflection::AbstractReflection.include(ActiveRecord::Reflection::AbstractReflection)
|
131
141
|
::ActiveRecord::Reflection::AssociationReflection.prepend(ActiveRecord::Reflection::AssociationScopeCache)
|
132
142
|
::ActiveRecord::Reflection::ThroughReflection.prepend(ActiveRecord::Reflection::AssociationScopeCache)
|
133
143
|
::ActiveRecord::Reflection::AssociationReflection.prepend(ActiveRecord::Reflection::AssociationReflection)
|
134
|
-
::ActiveRecord::Relation.prepend(ActiveRecord::Batches)
|
135
144
|
::ActiveRecord::Relation.prepend(ActiveRecord::Calculations)
|
136
145
|
::ActiveRecord::Relation.include(ActiveRecord::FinderMethods)
|
137
146
|
::ActiveRecord::Relation.include(ActiveRecord::QueryMethods)
|
@@ -140,8 +149,10 @@ module Switchman
|
|
140
149
|
::ActiveRecord::Relation.include(ActiveRecord::SpawnMethods)
|
141
150
|
::ActiveRecord::Relation.include(CallSuper)
|
142
151
|
|
143
|
-
::ActiveRecord::Relation::WhereClauseFactory.prepend(ActiveRecord::WhereClauseFactory)
|
144
152
|
::ActiveRecord::PredicateBuilder::AssociationQueryValue.prepend(ActiveRecord::PredicateBuilder::AssociationQueryValue)
|
153
|
+
|
154
|
+
::ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(ActiveRecord::Tasks::DatabaseTasks)
|
155
|
+
|
145
156
|
::ActiveRecord::TypeCaster::Map.include(ActiveRecord::TypeCaster::Map)
|
146
157
|
::ActiveRecord::TypeCaster::Connection.include(ActiveRecord::TypeCaster::Connection)
|
147
158
|
|
@@ -153,12 +164,10 @@ module Switchman
|
|
153
164
|
end
|
154
165
|
|
155
166
|
def self.foreign_key_check(name, type, limit: nil)
|
156
|
-
if name.to_s =~ /_id\z/ && type.to_s == 'integer' && limit.to_i < 8
|
157
|
-
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`"
|
158
|
-
end
|
167
|
+
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
|
159
168
|
end
|
160
169
|
|
161
|
-
initializer 'switchman.extend_connection_adapters', :
|
170
|
+
initializer 'switchman.extend_connection_adapters', after: 'active_record.initialize_database' do
|
162
171
|
::ActiveSupport.on_load(:active_record) do
|
163
172
|
::ActiveRecord::ConnectionAdapters::AbstractAdapter.descendants.each do |klass|
|
164
173
|
klass.prepend(ActiveRecord::AbstractAdapter::ForeignKeyCheck)
|
@@ -168,15 +177,11 @@ module Switchman
|
|
168
177
|
::ActiveRecord::ConnectionAdapters::TableDefinition.prepend(ActiveRecord::TableDefinition)
|
169
178
|
|
170
179
|
if defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
171
|
-
require
|
180
|
+
require 'switchman/active_record/postgresql_adapter'
|
172
181
|
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(ActiveRecord::PostgreSQLAdapter)
|
173
182
|
end
|
174
183
|
|
175
|
-
|
176
|
-
# establish a connection here instead
|
177
|
-
if !Shard.instance_variable_get(:@default)
|
178
|
-
::ActiveRecord::Base.establish_connection
|
179
|
-
end
|
184
|
+
Shard.send(:initialize_sharding)
|
180
185
|
end
|
181
186
|
end
|
182
187
|
|
@@ -187,21 +192,20 @@ module Switchman
|
|
187
192
|
end
|
188
193
|
end
|
189
194
|
|
190
|
-
initializer 'switchman.extend_guard_rail', :
|
195
|
+
initializer 'switchman.extend_guard_rail', before: 'switchman.extend_ar' do
|
191
196
|
::ActiveSupport.on_load(:active_record) do
|
192
|
-
require
|
197
|
+
require 'switchman/guard_rail'
|
193
198
|
|
194
199
|
::GuardRail.singleton_class.prepend(GuardRail::ClassMethods)
|
195
200
|
end
|
196
201
|
end
|
197
202
|
|
198
|
-
initializer 'switchman.extend_controller', :
|
203
|
+
initializer 'switchman.extend_controller', after: 'guard_rail.extend_ar' do
|
199
204
|
::ActiveSupport.on_load(:action_controller) do
|
200
|
-
require
|
205
|
+
require 'switchman/action_controller/caching'
|
201
206
|
|
202
207
|
::ActionController::Base.include(ActionController::Caching)
|
203
208
|
end
|
204
209
|
end
|
205
|
-
|
206
210
|
end
|
207
211
|
end
|
@@ -4,17 +4,13 @@ require 'etc'
|
|
4
4
|
|
5
5
|
module Switchman
|
6
6
|
class Environment
|
7
|
+
def self.cpu_count(nproc_bin = 'nproc')
|
8
|
+
return Etc.nprocessors if Etc.respond_to?(:nprocessors)
|
7
9
|
|
8
|
-
|
9
|
-
if Etc.respond_to?(:nprocessors)
|
10
|
-
return Etc.nprocessors
|
11
|
-
end
|
12
|
-
|
13
|
-
return `#{nproc_bin}`.to_i
|
10
|
+
`#{nproc_bin}`.to_i
|
14
11
|
rescue Errno::ENOENT
|
15
12
|
# an environment where nproc` isnt available
|
16
|
-
|
13
|
+
0
|
17
14
|
end
|
18
|
-
|
19
15
|
end
|
20
16
|
end
|
data/lib/switchman/errors.rb
CHANGED
data/lib/switchman/guard_rail.rb
CHANGED
@@ -3,27 +3,14 @@
|
|
3
3
|
module Switchman
|
4
4
|
module GuardRail
|
5
5
|
module ClassMethods
|
6
|
-
def
|
7
|
-
|
6
|
+
def activate(role)
|
7
|
+
DatabaseServer.send(:reference_role, role)
|
8
|
+
super
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
environment ||= :primary
|
14
|
-
activated_environments << environment
|
15
|
-
old_environment = self.environment
|
16
|
-
Thread.current[:guard_rail_environment] = environment
|
17
|
-
old_environment
|
18
|
-
end
|
19
|
-
|
20
|
-
# since activate! really is just a variable swap now, it's safe to use in
|
21
|
-
# the ensure block, simplifying the implementation
|
22
|
-
def activate(environment)
|
23
|
-
old_environment = activate!(environment)
|
24
|
-
yield
|
25
|
-
ensure
|
26
|
-
activate!(old_environment)
|
11
|
+
def activate!(role)
|
12
|
+
DatabaseServer.send(:reference_role, role)
|
13
|
+
super
|
27
14
|
end
|
28
15
|
end
|
29
16
|
end
|
@@ -4,19 +4,17 @@ module Switchman
|
|
4
4
|
module GuardRail
|
5
5
|
module Relation
|
6
6
|
def exec_queries(*args)
|
7
|
-
if
|
8
|
-
db = Shard.current(
|
9
|
-
if ::GuardRail.environment != db.guard_rail_environment
|
10
|
-
return db.unguard { super }
|
11
|
-
end
|
7
|
+
if lock_value
|
8
|
+
db = Shard.current(connection_classes).database_server
|
9
|
+
return db.unguard { super } if ::GuardRail.environment != db.guard_rail_environment
|
12
10
|
end
|
13
11
|
super
|
14
12
|
end
|
15
13
|
|
16
|
-
%w
|
14
|
+
%w[update_all delete_all].each do |method|
|
17
15
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
18
16
|
def #{method}(*args)
|
19
|
-
db = Shard.current(
|
17
|
+
db = Shard.current(connection_classes).database_server
|
20
18
|
if ::GuardRail.environment != db.guard_rail_environment
|
21
19
|
db.unguard { super }
|
22
20
|
else
|
@@ -1,16 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'switchman/test_helper'
|
4
4
|
|
5
5
|
module Switchman
|
6
6
|
# including this module in your specs will give you several shards to
|
7
7
|
# work with during specs:
|
8
8
|
# * Shard.default - the test database itself
|
9
|
-
# * @shard1 - a shard
|
9
|
+
# * @shard1 - a shard using the same connection as Shard.default
|
10
10
|
# * @shard2 - a shard using a dedicated connection
|
11
|
-
# * @shard3 - a shard using the same connection as @shard1 (this might
|
12
|
-
# be Shard.default if they already share a connection, or
|
13
|
-
# a separate shard)
|
14
11
|
module RSpecHelper
|
15
12
|
@@keep_the_shards = false
|
16
13
|
@@shard1 = nil
|
@@ -31,14 +28,15 @@ module Switchman
|
|
31
28
|
root_group.prepend_before(:all) do |group|
|
32
29
|
next if @@shard1
|
33
30
|
next if @@sharding_failed
|
31
|
+
|
34
32
|
# if we aren't actually going to run a sharding group/example,
|
35
33
|
# don't set it up after all
|
36
34
|
groups = group.class.descendant_filtered_examples.map(&:example_group).uniq
|
37
|
-
next unless groups.any?{ |
|
35
|
+
next unless groups.any? { |descendant_group| RSpecHelper.included_in?(descendant_group) }
|
38
36
|
|
39
|
-
puts
|
37
|
+
puts 'Setting up sharding for all specs...'
|
40
38
|
Shard.delete_all
|
41
|
-
Switchman.cache.delete(
|
39
|
+
Switchman.cache.delete('default_shard')
|
42
40
|
|
43
41
|
@@shard1, @@shard2 = TestHelper.recreate_persistent_test_shards
|
44
42
|
@@default_shard = Shard.default
|
@@ -49,23 +47,17 @@ module Switchman
|
|
49
47
|
begin
|
50
48
|
@@shard1 = @@shard1.create_new_shard
|
51
49
|
@@shard2 = @@shard2.create_new_shard
|
52
|
-
if @@shard1.database_server == Shard.default.database_server
|
53
|
-
@@shard3 = nil
|
54
|
-
else
|
55
|
-
@@shard3 = @@shard1.database_server.create_new_shard
|
56
|
-
end
|
57
50
|
rescue => e
|
58
|
-
|
51
|
+
warn 'Sharding setup FAILED!:'
|
59
52
|
while e
|
60
|
-
|
61
|
-
|
53
|
+
warn "\n#{e}\n"
|
54
|
+
warn e.backtrace
|
62
55
|
e = e.respond_to?(:cause) ? e.cause : nil
|
63
56
|
end
|
64
57
|
@@sharding_failed = true
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@@shard1 = @@shard2 = @@shard3 = nil
|
58
|
+
@@shard1&.drop_database rescue nil
|
59
|
+
@@shard2&.drop_database rescue nil
|
60
|
+
@@shard1 = @@shard2 = nil
|
69
61
|
Shard.delete_all
|
70
62
|
Shard.default(reload: true)
|
71
63
|
next
|
@@ -74,24 +66,20 @@ module Switchman
|
|
74
66
|
# we'll re-persist in the group's `before :all`; we don't want them to exist
|
75
67
|
# in the db before then
|
76
68
|
Shard.delete_all
|
77
|
-
Switchman.cache.delete(
|
69
|
+
Switchman.cache.delete('default_shard')
|
78
70
|
Shard.default(reload: true)
|
79
|
-
puts
|
71
|
+
puts 'Done!'
|
80
72
|
|
81
73
|
at_exit do
|
82
74
|
# preserve rspec's exit status
|
83
|
-
status= $!.is_a?(::SystemExit) ? $!.status : nil
|
84
|
-
puts
|
75
|
+
status = $!.is_a?(::SystemExit) ? $!.status : nil
|
76
|
+
puts 'Tearing down sharding for all specs'
|
85
77
|
@@shard1.database_server.destroy unless @@shard1.database_server == Shard.default.database_server
|
86
78
|
unless @@keep_the_shards
|
87
79
|
@@shard1.drop_database
|
88
80
|
@@shard1.destroy
|
89
81
|
@@shard2.drop_database
|
90
82
|
@@shard2.destroy
|
91
|
-
if @@shard3
|
92
|
-
@@shard3.drop_database
|
93
|
-
@@shard3.destroy
|
94
|
-
end
|
95
83
|
end
|
96
84
|
@@shard2.database_server.destroy
|
97
85
|
exit status if status
|
@@ -100,10 +88,11 @@ module Switchman
|
|
100
88
|
|
101
89
|
klass.before(:all) do
|
102
90
|
next if @@sharding_failed
|
91
|
+
|
103
92
|
dup = @@default_shard.dup
|
104
93
|
dup.id = @@default_shard.id
|
105
94
|
dup.save!
|
106
|
-
Switchman.cache.delete(
|
95
|
+
Switchman.cache.delete('default_shard')
|
107
96
|
Shard.default(reload: true)
|
108
97
|
dup = @@shard1.dup
|
109
98
|
dup.id = @@shard1.id
|
@@ -111,17 +100,12 @@ module Switchman
|
|
111
100
|
dup = @@shard2.dup
|
112
101
|
dup.id = @@shard2.id
|
113
102
|
dup.save!
|
114
|
-
if @@shard3
|
115
|
-
dup = @@shard3.dup
|
116
|
-
dup.id = @@shard3.id
|
117
|
-
dup.save!
|
118
|
-
end
|
119
103
|
@shard1, @shard2 = @@shard1, @@shard2
|
120
|
-
@shard3 = @@shard3 ? @@shard3 : Shard.default
|
121
104
|
end
|
122
105
|
|
123
106
|
klass.before do
|
124
|
-
raise
|
107
|
+
raise 'Sharding did not set up correctly' if @@sharding_failed
|
108
|
+
|
125
109
|
Shard.clear_cache
|
126
110
|
if use_transactional_tests
|
127
111
|
Shard.default(reload: true)
|
@@ -139,6 +123,7 @@ module Switchman
|
|
139
123
|
|
140
124
|
klass.after do
|
141
125
|
next if @@sharding_failed
|
126
|
+
|
142
127
|
if use_transactional_tests
|
143
128
|
shards = [@shard2]
|
144
129
|
shards << @shard1 unless @shard1.database_server == Shard.default.database_server
|
@@ -148,11 +133,18 @@ module Switchman
|
|
148
133
|
end
|
149
134
|
end
|
150
135
|
end
|
136
|
+
# clean up after specs
|
137
|
+
DatabaseServer.all.each do |ds|
|
138
|
+
if ds.fake? && ds != @shard2.database_server
|
139
|
+
ds.shards.delete_all unless use_transactional_tests
|
140
|
+
ds.destroy
|
141
|
+
end
|
142
|
+
end
|
151
143
|
end
|
152
144
|
|
153
145
|
klass.after(:all) do
|
154
146
|
Shard.connection.update("TRUNCATE #{Shard.quoted_table_name} CASCADE")
|
155
|
-
Switchman.cache.delete(
|
147
|
+
Switchman.cache.delete('default_shard')
|
156
148
|
Shard.default(reload: true)
|
157
149
|
end
|
158
150
|
end
|