switchman 1.6.1 → 2.0.9
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 +5 -5
- data/app/models/switchman/shard.rb +746 -11
- data/db/migrate/20130328212039_create_switchman_shards.rb +3 -1
- data/db/migrate/20130328224244_create_default_shard.rb +4 -2
- data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +13 -0
- data/db/migrate/20180828183945_add_default_shard_index.rb +15 -0
- data/db/migrate/20180828192111_add_timestamps_to_shards.rb +17 -0
- data/db/migrate/20190114212900_add_unique_name_indexes.rb +9 -0
- data/lib/switchman/action_controller/caching.rb +2 -0
- data/lib/switchman/active_record/abstract_adapter.rb +14 -4
- data/lib/switchman/active_record/association.rb +64 -37
- data/lib/switchman/active_record/attribute_methods.rb +16 -5
- data/lib/switchman/active_record/base.rb +67 -22
- data/lib/switchman/active_record/batches.rb +3 -1
- data/lib/switchman/active_record/calculations.rb +16 -21
- data/lib/switchman/active_record/connection_handler.rb +71 -79
- data/lib/switchman/active_record/connection_pool.rb +28 -23
- data/lib/switchman/active_record/finder_methods.rb +20 -29
- data/lib/switchman/active_record/log_subscriber.rb +14 -19
- data/lib/switchman/active_record/migration.rb +80 -0
- data/lib/switchman/active_record/model_schema.rb +3 -1
- data/lib/switchman/active_record/persistence.rb +9 -1
- data/lib/switchman/active_record/postgresql_adapter.rb +166 -126
- data/lib/switchman/active_record/predicate_builder.rb +2 -0
- data/lib/switchman/active_record/query_cache.rb +22 -87
- data/lib/switchman/active_record/query_methods.rb +122 -126
- data/lib/switchman/active_record/reflection.rb +37 -20
- data/lib/switchman/active_record/relation.rb +50 -29
- data/lib/switchman/active_record/spawn_methods.rb +2 -0
- data/lib/switchman/active_record/statement_cache.rb +44 -52
- data/lib/switchman/active_record/table_definition.rb +4 -2
- data/lib/switchman/active_record/type_caster.rb +2 -0
- data/lib/switchman/active_record/where_clause_factory.rb +5 -2
- data/lib/switchman/active_support/cache.rb +18 -0
- data/lib/switchman/arel.rb +8 -25
- data/lib/switchman/call_super.rb +19 -0
- data/lib/switchman/connection_pool_proxy.rb +70 -24
- data/lib/switchman/database_server.rb +69 -59
- data/lib/switchman/default_shard.rb +3 -0
- data/lib/switchman/engine.rb +42 -40
- data/lib/switchman/environment.rb +2 -0
- data/lib/switchman/errors.rb +2 -0
- data/lib/switchman/{shackles → guard_rail}/relation.rb +7 -5
- data/lib/switchman/{shackles.rb → guard_rail.rb} +6 -4
- data/lib/switchman/open4.rb +2 -0
- data/lib/switchman/r_spec_helper.rb +14 -8
- data/lib/switchman/rails.rb +2 -0
- data/lib/switchman/schema_cache.rb +17 -0
- data/lib/switchman/sharded_instrumenter.rb +4 -2
- data/lib/switchman/standard_error.rb +4 -2
- data/lib/switchman/test_helper.rb +6 -3
- data/lib/switchman/version.rb +3 -1
- data/lib/switchman.rb +3 -1
- data/lib/tasks/switchman.rake +46 -72
- metadata +87 -41
- data/app/models/switchman/shard_internal.rb +0 -692
|
@@ -1,19 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module StatementCache
|
|
4
6
|
module ClassMethods
|
|
5
|
-
def create(connection, block
|
|
7
|
+
def create(connection, &block)
|
|
6
8
|
relation = block.call ::ActiveRecord::StatementCache::Params.new
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
if ::Rails.version >= "5.2"
|
|
11
|
+
query_builder, binds = connection.cacheable_query(self, relation.arel)
|
|
12
|
+
bind_map = ::ActiveRecord::StatementCache::BindMap.new(binds)
|
|
13
|
+
new(relation.arel, bind_map, relation.klass)
|
|
14
|
+
else
|
|
15
|
+
bind_map = ::ActiveRecord::StatementCache::BindMap.new(relation.bound_attributes)
|
|
16
|
+
new relation.arel, bind_map
|
|
17
|
+
end
|
|
11
18
|
end
|
|
12
19
|
end
|
|
13
20
|
|
|
14
|
-
def initialize(arel, bind_map)
|
|
21
|
+
def initialize(arel, bind_map, klass=nil)
|
|
15
22
|
@arel = arel
|
|
16
23
|
@bind_map = bind_map
|
|
24
|
+
@klass = klass
|
|
17
25
|
@qualified_query_builders = {}
|
|
18
26
|
end
|
|
19
27
|
|
|
@@ -22,7 +30,13 @@ module Switchman
|
|
|
22
30
|
# we can make some assumptions about the shard source
|
|
23
31
|
# (e.g. infer from the primary key or use the current shard)
|
|
24
32
|
|
|
25
|
-
def execute(
|
|
33
|
+
def execute(*args)
|
|
34
|
+
if ::Rails.version >= '5.2'
|
|
35
|
+
params, connection = args
|
|
36
|
+
klass = @klass
|
|
37
|
+
else
|
|
38
|
+
params, klass, connection = args
|
|
39
|
+
end
|
|
26
40
|
target_shard = nil
|
|
27
41
|
if primary_index = bind_map.primary_value_index
|
|
28
42
|
primary_value = params[primary_index]
|
|
@@ -34,65 +48,43 @@ module Switchman
|
|
|
34
48
|
bind_values = bind_map.bind(params, current_shard, target_shard)
|
|
35
49
|
|
|
36
50
|
target_shard.activate(klass.shard_category) do
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
klass.find_by_sql(sql, bind_values)
|
|
40
|
-
else
|
|
41
|
-
sql = generic_query_builder(connection).sql_for(bind_values, connection)
|
|
42
|
-
klass.find_by_sql(sql, bind_values)
|
|
43
|
-
end
|
|
51
|
+
sql = qualified_query_builder(target_shard, klass).sql_for(bind_values, connection)
|
|
52
|
+
klass.find_by_sql(sql, bind_values)
|
|
44
53
|
end
|
|
45
54
|
end
|
|
46
55
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
if ::Rails.version < '5.2'
|
|
57
|
+
def qualified_query_builder(shard, klass)
|
|
58
|
+
@qualified_query_builders[shard.id] ||= klass.connection.cacheable_query(self.class, @arel)
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
def qualified_query_builder(shard, klass)
|
|
62
|
+
@qualified_query_builders[shard.id] ||= klass.connection.cacheable_query(self.class, @arel).first
|
|
63
|
+
end
|
|
53
64
|
end
|
|
54
65
|
|
|
55
66
|
module BindMap
|
|
56
67
|
# performs id transposition here instead of query_methods.rb
|
|
57
68
|
def bind(values, current_shard, target_shard)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
new_value = values[i]
|
|
66
|
-
end
|
|
67
|
-
bas[offset] = ba.with_cast_value(new_value)
|
|
68
|
-
end
|
|
69
|
-
bas
|
|
70
|
-
else
|
|
71
|
-
bvs = @bind_values.map { |pair| pair.dup }
|
|
72
|
-
@indexes.each_with_index do |offset,i|
|
|
73
|
-
bv = bvs[offset]
|
|
74
|
-
if bv[1].sharded
|
|
75
|
-
bv[1] = Shard.relative_id_for(values[i], current_shard, target_shard || current_shard)
|
|
76
|
-
else
|
|
77
|
-
bv[1] = values[i]
|
|
78
|
-
end
|
|
69
|
+
bas = @bound_attributes.dup
|
|
70
|
+
@indexes.each_with_index do |offset,i|
|
|
71
|
+
ba = bas[offset]
|
|
72
|
+
if ba.is_a?(::ActiveRecord::Relation::QueryAttribute) && ba.value.sharded
|
|
73
|
+
new_value = Shard.relative_id_for(values[i], current_shard, target_shard || current_shard)
|
|
74
|
+
else
|
|
75
|
+
new_value = values[i]
|
|
79
76
|
end
|
|
80
|
-
|
|
77
|
+
bas[offset] = ba.with_cast_value(new_value)
|
|
81
78
|
end
|
|
79
|
+
bas
|
|
82
80
|
end
|
|
83
81
|
|
|
84
82
|
def primary_value_index
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
@indexes.index(primary_ba_index)
|
|
91
|
-
end
|
|
92
|
-
else
|
|
93
|
-
if primary_bv_index = @bind_values.index{|col, sub| sub.primary}
|
|
94
|
-
@indexes.index(primary_bv_index)
|
|
95
|
-
end
|
|
83
|
+
primary_ba_index = @bound_attributes.index do |ba|
|
|
84
|
+
ba.is_a?(::ActiveRecord::Relation::QueryAttribute) && ba.value.primary
|
|
85
|
+
end
|
|
86
|
+
if primary_ba_index
|
|
87
|
+
@indexes.index(primary_ba_index)
|
|
96
88
|
end
|
|
97
89
|
end
|
|
98
90
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module TableDefinition
|
|
4
|
-
def column(name, type,
|
|
5
|
-
Engine.foreign_key_check(name, type,
|
|
6
|
+
def column(name, type, limit: nil, **)
|
|
7
|
+
Engine.foreign_key_check(name, type, limit: limit)
|
|
6
8
|
super
|
|
7
9
|
end
|
|
8
10
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module WhereClauseFactory
|
|
@@ -19,9 +21,10 @@ module Switchman
|
|
|
19
21
|
super
|
|
20
22
|
when Hash, ::Arel::Nodes::Node
|
|
21
23
|
where_clause = super
|
|
24
|
+
binds = ::Rails.version >= "5.2" ? nil : where_clause.binds
|
|
22
25
|
predicates = where_clause.send(:predicates)
|
|
23
|
-
@scope.send(:infer_shards_from_primary_key, predicates,
|
|
24
|
-
predicates = @scope.transpose_predicates(predicates, nil, @scope.primary_shard, false,
|
|
26
|
+
@scope.send(:infer_shards_from_primary_key, predicates, binds) if @scope.shard_source_value == :implicit && @scope.shard_value.is_a?(Shard)
|
|
27
|
+
predicates, _new_binds = @scope.transpose_predicates(predicates, nil, @scope.primary_shard, false, binds: binds)
|
|
25
28
|
where_clause.instance_variable_set(:@predicates, predicates)
|
|
26
29
|
where_clause
|
|
27
30
|
else
|
|
@@ -1,13 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module ActiveSupport
|
|
3
5
|
module Cache
|
|
4
6
|
module ClassMethods
|
|
5
7
|
def lookup_store(*store_options)
|
|
6
8
|
store = super
|
|
9
|
+
# can't use defined?, because it's a _ruby_ autoloaded constant,
|
|
10
|
+
# so just checking that will cause it to get required
|
|
11
|
+
if store.class.name == "ActiveSupport::Cache::RedisCacheStore" && !::ActiveSupport::Cache::RedisCacheStore.ancestors.include?(RedisCacheStore)
|
|
12
|
+
::ActiveSupport::Cache::RedisCacheStore.prepend(RedisCacheStore)
|
|
13
|
+
end
|
|
7
14
|
store.options[:namespace] ||= lambda { Shard.current.default? ? nil : "shard_#{Shard.current.id}" }
|
|
8
15
|
store
|
|
9
16
|
end
|
|
10
17
|
end
|
|
18
|
+
|
|
19
|
+
module RedisCacheStore
|
|
20
|
+
def clear(namespace: nil, **)
|
|
21
|
+
# RedisCacheStore tries to be smart and only clear the cache under your namespace, if you have one set
|
|
22
|
+
# unfortunately, it uses the keys command, which is extraordinarily inefficient in a large redis instance
|
|
23
|
+
# fortunately, we can assume we control the entire instance, because we set up the namespacing, so just
|
|
24
|
+
# always unset it temporarily for clear calls
|
|
25
|
+
namespace = nil
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
11
29
|
end
|
|
12
30
|
end
|
|
13
31
|
end
|
data/lib/switchman/arel.rb
CHANGED
|
@@ -1,35 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Switchman
|
|
2
4
|
module Arel
|
|
3
5
|
module Table
|
|
4
6
|
def model
|
|
5
|
-
|
|
6
|
-
type_caster.model
|
|
7
|
-
else
|
|
8
|
-
engine
|
|
9
|
-
end
|
|
7
|
+
type_caster.model
|
|
10
8
|
end
|
|
11
9
|
end
|
|
12
10
|
module Visitors
|
|
13
11
|
module ToSql
|
|
14
12
|
def visit_Arel_Nodes_TableAlias *args
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
o, collector = args
|
|
20
|
-
collector = visit o.relation, collector
|
|
21
|
-
collector << " "
|
|
22
|
-
collector << quote_local_table_name(o.name)
|
|
23
|
-
end
|
|
13
|
+
o, collector = args
|
|
14
|
+
collector = visit o.relation, collector
|
|
15
|
+
collector << " "
|
|
16
|
+
collector << quote_local_table_name(o.name)
|
|
24
17
|
end
|
|
25
18
|
|
|
26
19
|
def visit_Arel_Attributes_Attribute *args
|
|
27
20
|
o = args.first
|
|
28
21
|
join_name = o.relation.table_alias || o.relation.name
|
|
29
22
|
result = "#{quote_local_table_name join_name}.#{quote_column_name o.name}"
|
|
30
|
-
|
|
31
|
-
result = args.last << result
|
|
32
|
-
end
|
|
23
|
+
result = args.last << result
|
|
33
24
|
result
|
|
34
25
|
end
|
|
35
26
|
|
|
@@ -38,14 +29,6 @@ module Switchman
|
|
|
38
29
|
@connection.quote_local_table_name(name)
|
|
39
30
|
end
|
|
40
31
|
end
|
|
41
|
-
|
|
42
|
-
module PostgreSQL
|
|
43
|
-
# the only difference is to remove caching (which only applies to Arel < 6.0/AR < 4.2)
|
|
44
|
-
def quote_table_name name
|
|
45
|
-
return name if ::Arel::Nodes::SqlLiteral === name
|
|
46
|
-
@connection.quote_table_name(name)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
32
|
end
|
|
50
33
|
end
|
|
51
34
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Switchman
|
|
4
|
+
module CallSuper
|
|
5
|
+
def super_method_above(method_name, above_module)
|
|
6
|
+
method = method(method_name)
|
|
7
|
+
last_owner = method.owner
|
|
8
|
+
while method.owner != above_module
|
|
9
|
+
method = method.super_method
|
|
10
|
+
raise "Could not find super method ``#{method_name}' for #{self.class}" if method.owner == last_owner
|
|
11
|
+
end
|
|
12
|
+
method.super_method
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call_super(method, above_module, *args, &block)
|
|
16
|
+
super_method_above(method, above_module).call(*args, &block)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'switchman/schema_cache'
|
|
2
4
|
|
|
3
5
|
module Switchman
|
|
@@ -10,7 +12,7 @@ module Switchman
|
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
class ConnectionPoolProxy
|
|
13
|
-
delegate :spec, :connected?, :default_schema, :with_connection,
|
|
15
|
+
delegate :spec, :connected?, :default_schema, :with_connection, :query_cache_enabled, :active_connection?,
|
|
14
16
|
:to => :current_pool
|
|
15
17
|
|
|
16
18
|
attr_reader :category, :schema_cache
|
|
@@ -23,44 +25,51 @@ module Switchman
|
|
|
23
25
|
@category = category
|
|
24
26
|
@default_pool = default_pool
|
|
25
27
|
@connection_pools = shard_connection_pools
|
|
26
|
-
@schema_cache =
|
|
28
|
+
@schema_cache = default_pool.get_schema_cache(nil) if ::Rails.version >= '6'
|
|
29
|
+
@schema_cache = SchemaCache.new(self) unless @schema_cache.is_a?(SchemaCache)
|
|
30
|
+
if ::Rails.version >= '6'
|
|
31
|
+
@default_pool.set_schema_cache(@schema_cache)
|
|
32
|
+
@connection_pools.each_value do |pool|
|
|
33
|
+
pool.set_schema_cache(@schema_cache)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
27
36
|
end
|
|
28
37
|
|
|
29
38
|
def active_shard
|
|
30
39
|
Shard.current(@category)
|
|
31
40
|
end
|
|
32
41
|
|
|
33
|
-
def
|
|
34
|
-
::Rails.env.test? ? :
|
|
42
|
+
def active_guard_rail_environment
|
|
43
|
+
::Rails.env.test? ? :primary : active_shard.database_server.guard_rail_environment
|
|
35
44
|
end
|
|
36
45
|
|
|
37
46
|
def current_pool
|
|
38
47
|
current_active_shard = active_shard
|
|
39
|
-
pool = self.default_pool if current_active_shard.database_server == Shard.default.database_server &&
|
|
48
|
+
pool = self.default_pool if current_active_shard.database_server == Shard.default.database_server && active_guard_rail_environment == :primary && (current_active_shard.default? || current_active_shard.database_server.shareable?)
|
|
40
49
|
pool = @connection_pools[pool_key] ||= create_pool unless pool
|
|
41
50
|
pool.shard = current_active_shard
|
|
42
51
|
pool
|
|
43
52
|
end
|
|
44
53
|
|
|
45
54
|
def connections
|
|
46
|
-
|
|
55
|
+
connection_pools.map(&:connections).inject([], &:+)
|
|
47
56
|
end
|
|
48
57
|
|
|
49
|
-
def connection
|
|
58
|
+
def connection(switch_shard: true)
|
|
50
59
|
pool = current_pool
|
|
51
60
|
begin
|
|
52
|
-
connection = pool.connection
|
|
53
|
-
connection.instance_variable_set(:@schema_cache, @schema_cache)
|
|
61
|
+
connection = pool.connection(switch_shard: switch_shard)
|
|
62
|
+
connection.instance_variable_set(:@schema_cache, @schema_cache) unless ::Rails.version >= '6'
|
|
54
63
|
connection
|
|
55
64
|
rescue ConnectionError
|
|
56
|
-
raise if active_shard.database_server == Shard.default.database_server &&
|
|
57
|
-
configs = active_shard.database_server.config(
|
|
65
|
+
raise if active_shard.database_server == Shard.default.database_server && active_guard_rail_environment == :primary
|
|
66
|
+
configs = active_shard.database_server.config(active_guard_rail_environment)
|
|
58
67
|
raise unless configs.is_a?(Array)
|
|
59
68
|
configs.each_with_index do |config, idx|
|
|
60
69
|
pool = create_pool(config.dup)
|
|
61
70
|
begin
|
|
62
71
|
connection = pool.connection
|
|
63
|
-
connection.instance_variable_set(:@schema_cache, @schema_cache)
|
|
72
|
+
connection.instance_variable_set(:@schema_cache, @schema_cache) unless ::Rails.version >= '6'
|
|
64
73
|
rescue ConnectionError
|
|
65
74
|
raise if idx == configs.length - 1
|
|
66
75
|
next
|
|
@@ -71,22 +80,53 @@ module Switchman
|
|
|
71
80
|
end
|
|
72
81
|
end
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
def get_schema_cache(_connection)
|
|
84
|
+
@schema_cache
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def set_schema_cache(cache)
|
|
88
|
+
@schema_cache.copy_values(cache)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
%w{release_connection
|
|
92
|
+
disconnect!
|
|
93
|
+
flush!
|
|
94
|
+
clear_reloadable_connections!
|
|
95
|
+
verify_active_connections!
|
|
96
|
+
clear_stale_cached_connections!
|
|
97
|
+
enable_query_cache!
|
|
98
|
+
disable_query_cache! }.each do |method|
|
|
99
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
76
100
|
def #{method}
|
|
77
|
-
|
|
101
|
+
connection_pools.each(&:#{method})
|
|
78
102
|
end
|
|
79
|
-
|
|
103
|
+
RUBY
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def discard!
|
|
107
|
+
# this breaks everything if i try to pass it onto the pools and i'm not sure why
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def automatic_reconnect=(value)
|
|
111
|
+
connection_pools.each { |pool| pool.automatic_reconnect = value }
|
|
80
112
|
end
|
|
81
113
|
|
|
82
114
|
def clear_idle_connections!(since_when)
|
|
83
|
-
|
|
115
|
+
connection_pools.each { |pool| pool.clear_idle_connections!(since_when) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def remove_shard!(shard)
|
|
119
|
+
connection_pools.each { |pool| pool.remove_shard!(shard) }
|
|
84
120
|
end
|
|
85
121
|
|
|
86
122
|
protected
|
|
87
123
|
|
|
124
|
+
def connection_pools
|
|
125
|
+
(@connection_pools.values + [default_pool]).uniq
|
|
126
|
+
end
|
|
127
|
+
|
|
88
128
|
def pool_key
|
|
89
|
-
[
|
|
129
|
+
[active_guard_rail_environment,
|
|
90
130
|
active_shard.database_server.shareable? ? active_shard.database_server.pool_key : active_shard]
|
|
91
131
|
end
|
|
92
132
|
|
|
@@ -94,7 +134,7 @@ module Switchman
|
|
|
94
134
|
shard = active_shard
|
|
95
135
|
unless config
|
|
96
136
|
if shard != Shard.default
|
|
97
|
-
config = shard.database_server.config(
|
|
137
|
+
config = shard.database_server.config(active_guard_rail_environment)
|
|
98
138
|
config = config.first if config.is_a?(Array)
|
|
99
139
|
config = config.dup
|
|
100
140
|
else
|
|
@@ -104,22 +144,28 @@ module Switchman
|
|
|
104
144
|
# different models could be using different configs on the default
|
|
105
145
|
# shard, and database server wouldn't know about that
|
|
106
146
|
config = default_pool.spec.instance_variable_get(:@config)
|
|
107
|
-
if config[
|
|
108
|
-
config = config.merge(config[
|
|
109
|
-
elsif config[
|
|
110
|
-
config = config.merge(config[
|
|
147
|
+
if config[active_guard_rail_environment].is_a?(Hash)
|
|
148
|
+
config = config.merge(config[active_guard_rail_environment])
|
|
149
|
+
elsif config[active_guard_rail_environment].is_a?(Array)
|
|
150
|
+
config = config.merge(config[active_guard_rail_environment].first)
|
|
111
151
|
else
|
|
112
152
|
config = config.dup
|
|
113
153
|
end
|
|
114
154
|
end
|
|
115
155
|
end
|
|
116
|
-
spec = ::ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(
|
|
156
|
+
spec = ::ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(
|
|
157
|
+
category,
|
|
158
|
+
config,
|
|
159
|
+
"#{config[:adapter]}_connection"
|
|
160
|
+
)
|
|
117
161
|
# unfortunately the AR code that does this require logic can't really be
|
|
118
162
|
# called in isolation
|
|
119
163
|
require "active_record/connection_adapters/#{config[:adapter]}_adapter"
|
|
120
164
|
|
|
121
165
|
::ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec).tap do |pool|
|
|
122
166
|
pool.shard = shard
|
|
167
|
+
pool.set_schema_cache(@schema_cache) if ::Rails.version >= '6'
|
|
168
|
+
pool.enable_query_cache! if !@connection_pools.empty? && @connection_pools.first.last.query_cache_enabled
|
|
123
169
|
end
|
|
124
170
|
end
|
|
125
171
|
end
|