activerecord-turntable 3.1.0 → 4.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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +25 -9
- data/CHANGELOG.md +25 -0
- data/Gemfile +2 -0
- data/Guardfile +1 -1
- data/README.md +202 -8
- data/Rakefile +42 -67
- data/activerecord-turntable.gemspec +3 -2
- data/gemfiles/rails5_0_0.gemfile +2 -0
- data/gemfiles/rails5_0_1.gemfile +2 -0
- data/gemfiles/rails5_0_2.gemfile +2 -0
- data/gemfiles/rails5_0_3.gemfile +2 -0
- data/gemfiles/rails5_0_4.gemfile +8 -0
- data/gemfiles/rails5_0_5.gemfile +8 -0
- data/gemfiles/rails5_1_0.gemfile +2 -0
- data/gemfiles/rails5_1_1.gemfile +2 -0
- data/gemfiles/rails5_1_2.gemfile +9 -0
- data/gemfiles/rails5_1_3.gemfile +9 -0
- data/gemfiles/rails5_1_4.gemfile +9 -0
- data/gemfiles/rails5_1_5.gemfile +9 -0
- data/lib/active_record/turntable.rb +10 -20
- data/lib/active_record/turntable/active_record_ext.rb +1 -1
- data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +5 -1
- data/lib/active_record/turntable/active_record_ext/sequencer.rb +11 -11
- data/lib/active_record/turntable/active_record_ext/transactions.rb +5 -4
- data/lib/active_record/turntable/algorithm.rb +12 -0
- data/lib/active_record/turntable/algorithm/base.rb +6 -2
- data/lib/active_record/turntable/algorithm/hash_slot_algorithm.rb +35 -0
- data/lib/active_record/turntable/algorithm/modulo_algorithm.rb +3 -7
- data/lib/active_record/turntable/algorithm/range_algorithm.rb +3 -34
- data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +16 -28
- data/lib/active_record/turntable/base.rb +43 -39
- data/lib/active_record/turntable/cluster.rb +31 -29
- data/lib/active_record/turntable/cluster_helper_methods.rb +12 -2
- data/lib/active_record/turntable/cluster_registry.rb +7 -0
- data/lib/active_record/turntable/configuration.rb +50 -0
- data/lib/active_record/turntable/configuration/dsl.rb +79 -0
- data/lib/active_record/turntable/configuration/loader.rb +10 -0
- data/lib/active_record/turntable/configuration/loader/dsl.rb +23 -0
- data/lib/active_record/turntable/configuration/loader/yaml.rb +62 -0
- data/lib/active_record/turntable/configuration_methods.rb +26 -0
- data/lib/active_record/turntable/connection_proxy.rb +51 -40
- data/lib/active_record/turntable/{master_shard.rb → default_shard.rb} +6 -2
- data/lib/active_record/turntable/deprecation.rb +8 -0
- data/lib/active_record/turntable/error.rb +2 -1
- data/lib/active_record/turntable/migration.rb +3 -7
- data/lib/active_record/turntable/mixer.rb +10 -10
- data/lib/active_record/turntable/mixer/fader.rb +1 -1
- data/lib/active_record/turntable/pool_proxy.rb +5 -3
- data/lib/active_record/turntable/railtie.rb +11 -4
- data/lib/active_record/turntable/seq_shard.rb +8 -9
- data/lib/active_record/turntable/sequencer.rb +18 -43
- data/lib/active_record/turntable/sequencer/api.rb +3 -5
- data/lib/active_record/turntable/sequencer/barrage.rb +1 -2
- data/lib/active_record/turntable/sequencer/katsubushi.rb +27 -0
- data/lib/active_record/turntable/sequencer/mysql.rb +14 -6
- data/lib/active_record/turntable/sequencer_registry.rb +30 -0
- data/lib/active_record/turntable/shard.rb +31 -10
- data/lib/active_record/turntable/shard_registry.rb +36 -0
- data/lib/active_record/turntable/slave_registry.rb +21 -0
- data/lib/active_record/turntable/slave_shard.rb +9 -0
- data/lib/active_record/turntable/version.rb +1 -1
- data/lib/generators/templates/turntable.rb +50 -0
- data/lib/generators/templates/turntable.yml +18 -0
- metadata +54 -20
- data/lib/active_record/turntable/config.rb +0 -26
|
@@ -5,20 +5,33 @@ module ActiveRecord::Turntable
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
|
-
class_attribute :turntable_connections, :turntable_clusters,
|
|
9
|
-
:turntable_enabled, :turntable_sequencer_enabled
|
|
8
|
+
class_attribute :turntable_connections, :turntable_clusters, :turntable_sequencers,
|
|
9
|
+
:turntable_enabled, :turntable_sequencer_enabled, :turntable_configuration
|
|
10
10
|
|
|
11
11
|
self.turntable_connections = {}
|
|
12
12
|
self.turntable_clusters = {}.with_indifferent_access
|
|
13
|
+
self.turntable_sequencers = {}.with_indifferent_access
|
|
13
14
|
self.turntable_enabled = false
|
|
14
15
|
self.turntable_sequencer_enabled = false
|
|
16
|
+
|
|
15
17
|
class << self
|
|
16
18
|
delegate :shards_transaction, :with_all, to: :connection
|
|
17
|
-
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
def reset_turntable_configuration(configuration, reset = true)
|
|
21
|
+
old = self.turntable_configuration
|
|
22
|
+
self.turntable_configuration = configuration
|
|
23
|
+
|
|
24
|
+
old.release! if old
|
|
25
|
+
|
|
26
|
+
if reset
|
|
27
|
+
# TODO: replace exitsting connection_pool when configurations reloaded
|
|
28
|
+
self.turntable_clusters = turntable_configuration.clusters
|
|
29
|
+
self.turntable_sequencers = turntable_configuration.sequencers
|
|
30
|
+
ActiveSupport.run_load_hooks(:turntable_configuration_loaded, ActiveRecord::Base)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
21
33
|
end
|
|
34
|
+
|
|
22
35
|
include ClusterHelperMethods
|
|
23
36
|
end
|
|
24
37
|
|
|
@@ -27,20 +40,18 @@ module ActiveRecord::Turntable
|
|
|
27
40
|
# @param [Symbol] shard_key_name shard key attribute name
|
|
28
41
|
# @param [Hash] options
|
|
29
42
|
def turntable(cluster_name, shard_key_name, options = {})
|
|
30
|
-
class_attribute :turntable_shard_key,
|
|
31
|
-
:turntable_cluster, :turntable_cluster_name
|
|
43
|
+
class_attribute :turntable_shard_key, :turntable_cluster_name
|
|
32
44
|
|
|
33
45
|
self.turntable_enabled = true
|
|
34
46
|
self.turntable_cluster_name = cluster_name
|
|
35
47
|
self.turntable_shard_key = shard_key_name
|
|
36
|
-
self.turntable_cluster =
|
|
37
|
-
self.turntable_clusters[cluster_name] ||= Cluster.new(
|
|
38
|
-
turntable_config[:clusters][cluster_name],
|
|
39
|
-
options
|
|
40
|
-
)
|
|
41
48
|
turntable_replace_connection_pool
|
|
42
49
|
end
|
|
43
50
|
|
|
51
|
+
def turntable_cluster
|
|
52
|
+
turntable_clusters[turntable_cluster_name]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
def turntable_replace_connection_pool
|
|
45
56
|
ch = connection_handler
|
|
46
57
|
cp = ConnectionProxy.new(self, turntable_cluster)
|
|
@@ -50,31 +61,22 @@ module ActiveRecord::Turntable
|
|
|
50
61
|
ch.send(:owner_to_pool)[connection_specification_name] = pp
|
|
51
62
|
end
|
|
52
63
|
|
|
53
|
-
def initialize_clusters!
|
|
54
|
-
turntable_config[:clusters].each do |name, spec|
|
|
55
|
-
self.turntable_clusters[name] ||= Cluster.new(spec)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def spec_for(config)
|
|
60
|
-
begin
|
|
61
|
-
require "active_record/connection_adapters/#{config['adapter']}_adapter"
|
|
62
|
-
rescue LoadError => e
|
|
63
|
-
raise "Please install the #{config['adapter']} adapter: `gem install activerecord-#{config['adapter']}-adapter` (#{e})"
|
|
64
|
-
end
|
|
65
|
-
adapter_method = "#{config['adapter']}_connection"
|
|
66
|
-
ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(config, adapter_method)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
64
|
def clear_all_connections!
|
|
70
65
|
turntable_connections.values.each(&:disconnect!)
|
|
71
66
|
end
|
|
72
67
|
|
|
73
|
-
def sequencer(
|
|
74
|
-
class_attribute :
|
|
68
|
+
def sequencer(sequencer_name, *args)
|
|
69
|
+
class_attribute :turntable_sequencer_name
|
|
70
|
+
class << self
|
|
71
|
+
prepend ActiveRecordExt::Sequencer
|
|
72
|
+
end
|
|
75
73
|
|
|
76
74
|
self.turntable_sequencer_enabled = true
|
|
77
|
-
self.
|
|
75
|
+
self.turntable_sequencer_name = sequencer_name
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def turntable_sequencer
|
|
79
|
+
turntable_sequencers[turntable_sequencer_name]
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
def turntable_enabled?
|
|
@@ -85,12 +87,8 @@ module ActiveRecord::Turntable
|
|
|
85
87
|
turntable_sequencer_enabled
|
|
86
88
|
end
|
|
87
89
|
|
|
88
|
-
def current_sequence
|
|
89
|
-
connection.current_sequence_value(self.sequence_name) if sequencer_enabled?
|
|
90
|
-
end
|
|
91
|
-
|
|
92
90
|
def current_last_shard
|
|
93
|
-
turntable_cluster.select_shard(
|
|
91
|
+
turntable_cluster.select_shard(current_sequence_value) if sequencer_enabled?
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
def with_shard(any_shard)
|
|
@@ -104,12 +102,18 @@ module ActiveRecord::Turntable
|
|
|
104
102
|
end
|
|
105
103
|
connection.with_shard(shard) { yield }
|
|
106
104
|
end
|
|
107
|
-
end
|
|
108
105
|
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
def with_slave
|
|
107
|
+
connection.with_slave { yield }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def with_master
|
|
111
|
+
connection.with_master { yield }
|
|
112
|
+
end
|
|
111
113
|
end
|
|
112
114
|
|
|
115
|
+
delegate :shards_transaction, :turntable_cluster, to: :class
|
|
116
|
+
|
|
113
117
|
# @return [ActiveRecord::Turntable::Shard] current shard for self
|
|
114
118
|
def turntable_shard
|
|
115
119
|
turntable_cluster.shard_for(self.send(turntable_shard_key))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "active_support/core_ext/hash/indifferent_access"
|
|
2
|
+
require "concurrent/atomic/thread_local_var"
|
|
2
3
|
|
|
3
4
|
module ActiveRecord::Turntable
|
|
4
5
|
class Cluster
|
|
@@ -7,40 +8,27 @@ module ActiveRecord::Turntable
|
|
|
7
8
|
"algorithm" => "range",
|
|
8
9
|
}.with_indifferent_access
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
@config = DEFAULT_CONFIG.merge(cluster_spec)
|
|
12
|
-
@options = options.with_indifferent_access
|
|
13
|
-
@shards = {}.with_indifferent_access
|
|
11
|
+
attr_accessor :algorithm, :shard_registry, :sequencer_registry
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if seq
|
|
18
|
-
if seq.values.size > 0 && seq.values.first[:seq_type] == "mysql"
|
|
19
|
-
@seq_shard = SeqShard.new(seq.values.first)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# setup shards
|
|
24
|
-
@config[:shards].each do |spec|
|
|
25
|
-
@shards[spec[:connection]] ||= Shard.new(spec)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# setup algorithm
|
|
29
|
-
alg_name = "ActiveRecord::Turntable::Algorithm::#{@config[:algorithm].camelize}Algorithm"
|
|
30
|
-
@algorithm = alg_name.constantize.new(@config)
|
|
13
|
+
def initialize
|
|
14
|
+
@slave_enabled = Concurrent::ThreadLocalVar.new(false)
|
|
31
15
|
end
|
|
32
16
|
|
|
33
|
-
def
|
|
34
|
-
|
|
17
|
+
def self.build(sequencer_registry)
|
|
18
|
+
self.new.tap do |instance|
|
|
19
|
+
instance.shard_registry = ShardRegistry.new(instance)
|
|
20
|
+
instance.sequencer_registry = sequencer_registry
|
|
21
|
+
yield instance
|
|
22
|
+
end
|
|
35
23
|
end
|
|
36
24
|
|
|
37
|
-
|
|
25
|
+
delegate :shards, :shard_maps, :release!, to: :shard_registry
|
|
38
26
|
|
|
39
27
|
def shard_for(key)
|
|
40
|
-
|
|
28
|
+
algorithm.choose(shard_maps, key)
|
|
41
29
|
rescue
|
|
42
30
|
raise ActiveRecord::Turntable::CannotSpecifyShardError,
|
|
43
|
-
"cannot
|
|
31
|
+
"cannot select shard for key:#{key.inspect}"
|
|
44
32
|
end
|
|
45
33
|
|
|
46
34
|
def select_shard(key)
|
|
@@ -52,7 +40,7 @@ module ActiveRecord::Turntable
|
|
|
52
40
|
unless in_recursion
|
|
53
41
|
shards = Array.wrap(shards).dup
|
|
54
42
|
if shards.blank?
|
|
55
|
-
shards =
|
|
43
|
+
shards = self.shards.dup
|
|
56
44
|
end
|
|
57
45
|
end
|
|
58
46
|
shard = to_shard(shards.shift)
|
|
@@ -83,10 +71,24 @@ module ActiveRecord::Turntable
|
|
|
83
71
|
end
|
|
84
72
|
end
|
|
85
73
|
|
|
74
|
+
def slave_enabled?
|
|
75
|
+
@slave_enabled.value
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def set_slave_enabled(enabled)
|
|
79
|
+
@slave_enabled.value = enabled
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def sequencers
|
|
83
|
+
sequencer_registry.all
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def sequencer(name)
|
|
87
|
+
sequencers[name]
|
|
88
|
+
end
|
|
89
|
+
|
|
86
90
|
def weighted_shards(key = nil)
|
|
87
|
-
|
|
88
|
-
[@shards[k], v]
|
|
89
|
-
end]
|
|
91
|
+
@algorithm.shard_weights(shard_maps, key)
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
end
|
|
@@ -3,7 +3,7 @@ module ActiveRecord::Turntable
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
|
-
ActiveSupport.on_load(:
|
|
6
|
+
ActiveSupport.on_load(:turntable_configuration_loaded) do
|
|
7
7
|
turntable_clusters.each do |name, _cluster|
|
|
8
8
|
turntable_define_cluster_methods(name)
|
|
9
9
|
end
|
|
@@ -42,8 +42,18 @@ module ActiveRecord::Turntable
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
def spec_for(config)
|
|
46
|
+
begin
|
|
47
|
+
require "active_record/connection_adapters/#{config["adapter"]}_adapter"
|
|
48
|
+
rescue LoadError => e
|
|
49
|
+
raise "Please install the #{config["adapter"]} adapter: `gem install activerecord-#{config["adapter"]}-adapter` (#{e})"
|
|
50
|
+
end
|
|
51
|
+
adapter_method = "#{config["adapter"]}_connection"
|
|
52
|
+
ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(config, adapter_method)
|
|
53
|
+
end
|
|
54
|
+
|
|
45
55
|
def weighted_random_shard_with(*klasses, &block)
|
|
46
|
-
shards_weight = self.turntable_cluster.weighted_shards(self.
|
|
56
|
+
shards_weight = self.turntable_cluster.weighted_shards(self.current_sequence_value(sequence_name))
|
|
47
57
|
sum = shards_weight.values.inject(&:+)
|
|
48
58
|
idx = rand(sum)
|
|
49
59
|
shard, _weight = shards_weight.find { |_k, v|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module ActiveRecord::Turntable
|
|
2
|
+
class Configuration
|
|
3
|
+
extend ActiveSupport::Autoload
|
|
4
|
+
autoload :DSL
|
|
5
|
+
autoload :Loader
|
|
6
|
+
|
|
7
|
+
attr_reader :cluster_registry, :sequencer_registry
|
|
8
|
+
attr_accessor :raise_on_not_specified_shard_query,
|
|
9
|
+
:raise_on_not_specified_shard_update
|
|
10
|
+
alias_method :configure, :instance_exec
|
|
11
|
+
alias_method :clusters, :cluster_registry
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@cluster_registry = ClusterRegistry.new
|
|
15
|
+
@sequencer_registry = SequencerRegistry.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def cluster(name)
|
|
19
|
+
cluster_registry[name]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def sequencers
|
|
23
|
+
sequencer_registry.sequencers
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def sequencer(name)
|
|
27
|
+
sequencer_registry[name]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def release!
|
|
31
|
+
cluster_registry.release!
|
|
32
|
+
sequencer_registry.release!
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.configure(&block)
|
|
36
|
+
new.tap { |c| c.configure(&block) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.load(path, env)
|
|
40
|
+
case File.extname(path)
|
|
41
|
+
when ".yml"
|
|
42
|
+
Loader::YAML.load(path, env)
|
|
43
|
+
when ".rb"
|
|
44
|
+
Loader::DSL.load(path)
|
|
45
|
+
else
|
|
46
|
+
raise InvalidConfigurationError, "Invalid configuration file path: #{path}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require "active_record/turntable/configuration"
|
|
2
|
+
|
|
3
|
+
module ActiveRecord::Turntable
|
|
4
|
+
class Configuration
|
|
5
|
+
class DSL
|
|
6
|
+
attr_reader :configuration
|
|
7
|
+
|
|
8
|
+
def initialize(configuration = Configuration.new)
|
|
9
|
+
@configuration = configuration
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cluster(name, &block)
|
|
13
|
+
cluster_dsl = ClusterDSL.new(configuration).tap { |dsl| dsl.instance_exec(&block) }
|
|
14
|
+
configuration.clusters[name] = cluster_dsl.cluster
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
GLOBAL_SETTINGS_KEYS = %w(
|
|
18
|
+
raise_on_not_specified_shard_query
|
|
19
|
+
raise_on_not_specified_shard_update
|
|
20
|
+
).freeze
|
|
21
|
+
|
|
22
|
+
GLOBAL_SETTINGS_KEYS.each do |k|
|
|
23
|
+
define_method(k) do |value|
|
|
24
|
+
configuration.send("#{k}=", value)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def global_settings_keys
|
|
29
|
+
GLOBAL_SETTINGS_KEYS
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ClusterDSL < DSL
|
|
33
|
+
attr_reader :sequencers
|
|
34
|
+
|
|
35
|
+
def initialize(configuration)
|
|
36
|
+
super
|
|
37
|
+
@algorithm = Algorithm.class_for("range").new(nil)
|
|
38
|
+
@shard_settings = []
|
|
39
|
+
@sequencer_settings = []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def cluster
|
|
43
|
+
Cluster.build(configuration.sequencer_registry) do |c|
|
|
44
|
+
c.algorithm = @algorithm
|
|
45
|
+
@shard_settings.each do |setting|
|
|
46
|
+
c.shard_registry.add(setting)
|
|
47
|
+
end
|
|
48
|
+
@sequencer_settings.each do |name, type, options|
|
|
49
|
+
c.sequencer_registry.add(name, type, options, c)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def algorithm(type, options = {})
|
|
55
|
+
@algorithm = Algorithm.class_for(type.to_s).new(options)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def sequencer(sequencer_name, type, options = {})
|
|
59
|
+
@sequencer_settings << [sequencer_name.to_s, type.to_s, options]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
ShardSetting = Struct.new(:name, :range, :slaves) do
|
|
63
|
+
def range
|
|
64
|
+
case self[:range]
|
|
65
|
+
when Integer
|
|
66
|
+
self[:range]..self[:range]
|
|
67
|
+
else
|
|
68
|
+
self[:range]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def shard(range, slaves: [], to:)
|
|
74
|
+
@shard_settings << ShardSetting.new(to.to_s, range, slaves.map(&:to_s))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ActiveRecord::Turntable
|
|
2
|
+
class Configuration
|
|
3
|
+
class Loader::DSL
|
|
4
|
+
attr_reader :path, :configuration, :dsl
|
|
5
|
+
|
|
6
|
+
def initialize(path, configuration = Configuration.new)
|
|
7
|
+
@path = path
|
|
8
|
+
@configuration = configuration
|
|
9
|
+
@dsl = DSL.new(@configuration)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.load(path, configuration = Configuration.new)
|
|
13
|
+
new(path, configuration).load
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load
|
|
17
|
+
@dsl.instance_eval(File.read(@path), @path, 1)
|
|
18
|
+
|
|
19
|
+
configuration
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module ActiveRecord::Turntable
|
|
2
|
+
class Configuration
|
|
3
|
+
class Loader::YAML
|
|
4
|
+
attr_reader :path, :configuration, :dsl
|
|
5
|
+
|
|
6
|
+
def initialize(path, configuration = Configuration.new)
|
|
7
|
+
@path = path
|
|
8
|
+
@configuration = configuration
|
|
9
|
+
@dsl = DSL.new(@configuration)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.load(path, env, configuration = Configuration.new)
|
|
13
|
+
new(path, configuration).load(env)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load(env)
|
|
17
|
+
yaml = YAML.load(ERB.new(IO.read(path)).result).with_indifferent_access[env]
|
|
18
|
+
load_clusters(yaml[:clusters])
|
|
19
|
+
load_global_settings(yaml)
|
|
20
|
+
|
|
21
|
+
configuration
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def load_clusters(clusters_config)
|
|
27
|
+
clusters_config.each do |cluster_name, conf|
|
|
28
|
+
@dsl.cluster(cluster_name) do
|
|
29
|
+
algorithm conf[:algorithm] if conf[:algorithm]
|
|
30
|
+
|
|
31
|
+
if conf[:seq]
|
|
32
|
+
conf[:seq].each do |sequence_name, sequence_conf|
|
|
33
|
+
sequencer(sequence_name, (sequence_conf[:seq_type] || :mysql), sequence_conf)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if conf[:shards]
|
|
38
|
+
current_lower_limit = 1
|
|
39
|
+
conf[:shards].each do |shard_conf|
|
|
40
|
+
upper_limit = if shard_conf.has_key?(:less_than)
|
|
41
|
+
shard_conf[:less_than] - 1
|
|
42
|
+
else
|
|
43
|
+
current_lower_limit
|
|
44
|
+
end
|
|
45
|
+
shard current_lower_limit..upper_limit, to: shard_conf[:connection], slaves: Array.wrap(shard_conf[:slaves])
|
|
46
|
+
current_lower_limit = upper_limit + 1
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def load_global_settings(yaml)
|
|
54
|
+
yaml.each do |k, v|
|
|
55
|
+
if @dsl.global_settings_keys.include?(k)
|
|
56
|
+
@dsl.send(k, v)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|