activerecord-turntable 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a4bd6cbf61673b4f11bba18e22ff888a694f09a
4
- data.tar.gz: b94e9d04efa41f8b58f5b65bdcc51bd4cb2a890c
3
+ metadata.gz: 8b5ef39b2f1a9eaa4b861f4e7ac57aabc2fffa21
4
+ data.tar.gz: 9cf6ae9ab38f0ebc8268a63fe188ed354b14deb5
5
5
  SHA512:
6
- metadata.gz: 4c41774f64e47dde724ecd71b6eabe913c165d40ed159d73b867e0447ae64313437f0db4a4dcb98fb0e85f467ba3985b8a1974c6c97b558a9b793f115e093071
7
- data.tar.gz: 63184562e69d48c2b2ae73b70878d1b01e850c1caf5ff11fd7a21ebe3c5e157b12f4a84e79da4cb94b198fa82193aa86328f7b493078aaf5ac7644c9f59345c5
6
+ metadata.gz: 26b6729a9cfe48c15982a3c23b748a2cc23746a79a16cc6a522f9e84dab6095ad156b7d193d9c324c5a76b4ccdcbd5b295ef95ff306dbf396819bfee6d473502
7
+ data.tar.gz: b96d8f0a07f38f527e6298c48fa7017fb6ffb3596c78410f4a0b0ebb57c1c29446aec04b27d98ccc5c1a34aaa9f464460c6a87c58eb687f18690d679996896f0
@@ -1,3 +1,21 @@
1
+ ## activerecord-turntable 2.2.0 ##
2
+
3
+ ### Features
4
+
5
+ * Add `modulo` algorithm (thx tatsuma)
6
+
7
+ ### Improvements
8
+
9
+ * Add err detail to Building Fader exception log (thx tatsuma)
10
+
11
+ ### Bugfixes
12
+
13
+ * Fix building cluster with mysql sequencer (fixes #25) (thx tatsuma)
14
+
15
+ ### Documentation
16
+
17
+ * Fix seqeucner example (thx akicho8, tatsuma)
18
+
1
19
  ## activerecord-turntable 2.1.1 ##
2
20
 
3
21
  ### Bugfixes
data/README.md CHANGED
@@ -22,7 +22,7 @@ Currently supports mysql only.
22
22
  Add to Gemfile:
23
23
 
24
24
  ```ruby
25
- gem 'activerecord-turntable', '~> 2.0.0'
25
+ gem 'activerecord-turntable', '~> 2.1.1'
26
26
  ```
27
27
 
28
28
  Run a bundle install:
@@ -90,14 +90,14 @@ Edit turntable.yml and database.yml. See below example config.
90
90
  development:
91
91
  clusters:
92
92
  user_cluster: # <-- cluster name
93
- algorithm: range_bsearch # <-- `range` or `range_bsearch`
93
+ algorithm: range_bsearch # <-- `range`, `range_bsearch` or `modulo`
94
94
  seq:
95
95
  user_seq: # <-- sequencer name
96
96
  seq_type: mysql # <-- sequencer type
97
97
  connection: user_seq_1 # <-- sequencer database connection setting
98
98
  shards:
99
99
  - connection: user_shard_1 # <-- shard name
100
- less_than: 100 # <-- shard range(like mysql partitioning)
100
+ less_than: 100 # <-- shard range(like mysql partitioning) If you are using a modulo algorithm, it doesn't need it.
101
101
  - connection: user_shard_2
102
102
  less_than: 200
103
103
  - connection: user_shard_3
@@ -178,13 +178,13 @@ Add turntable [shard_key_name] to the model class:
178
178
  ```ruby
179
179
  class User < ActiveRecord::Base
180
180
  turntable :user_cluster, :id
181
- sequencer
181
+ sequencer :user_seq
182
182
  has_one :status
183
183
  end
184
184
 
185
185
  class Status < ActiveRecord::Base
186
186
  turntable :user_cluster, :user_id
187
- sequencer
187
+ sequencer :user_seq
188
188
  belongs_to :user
189
189
  end
190
190
  ```
@@ -296,7 +296,7 @@ Next, add sequencer definition to the model:
296
296
  ```ruby
297
297
  class User < ActiveRecord::Base
298
298
  turntable :id
299
- sequencer :users_seq # <-- this line enables sequencer module
299
+ sequencer :user_seq # <-- this line enables sequencer module
300
300
  has_one :status
301
301
  end
302
302
  ```
@@ -6,6 +6,7 @@ module ActiveRecord::Turntable
6
6
  autoload :Base
7
7
  autoload :RangeAlgorithm
8
8
  autoload :RangeBsearchAlgorithm
9
+ autoload :ModuloAlgorithm
9
10
  end
10
11
  end
11
12
  end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ module ActiveRecord::Turntable::Algorithm
3
+ class ModuloAlgorithm < Base
4
+ def initialize(config)
5
+ @config = config
6
+ end
7
+
8
+ def calculate(key)
9
+ @config["shards"][key % @config["shards"].size]["connection"]
10
+ rescue
11
+ raise ActiveRecord::Turntable::CannotSpecifyShardError, "cannot specify shard for key:#{key}"
12
+ end
13
+ end
14
+ end
@@ -14,8 +14,11 @@ module ActiveRecord::Turntable
14
14
  @shards = {}.with_indifferent_access
15
15
 
16
16
  # setup sequencer
17
- if (seq = (@options[:seq] || @config[:seq])) && seq[:type] == :mysql
18
- @seq_shard = SeqShard.new(seq)
17
+ seq = (@options[:seq] || @config[:seq])
18
+ if seq
19
+ if seq.values.size > 0 && seq.values.first["seq_type"] == "mysql"
20
+ @seq_shard = SeqShard.new(seq.values.first)
21
+ end
19
22
  end
20
23
 
21
24
  # setup shards
@@ -48,7 +48,7 @@ module ActiveRecord::Turntable
48
48
  method, query, *args, &block)
49
49
  end
50
50
  rescue Exception => err
51
- logger.warn { "[ActiveRecord::Turntable] Error on Building Fader: #{binded_query}, on_method: #{method_name}" }
51
+ logger.warn { "[ActiveRecord::Turntable] Error on Building Fader: #{binded_query}, on_method: #{method_name}, err: #{err}" }
52
52
  raise err
53
53
  end
54
54
 
@@ -2,6 +2,13 @@ module ActiveRecord::Turntable
2
2
  class SeqShard < Shard
3
3
  private
4
4
 
5
+ def create_connection_class
6
+ klass = get_or_set_connection_class
7
+ klass.remove_connection
8
+ klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:seq][name].with_indifferent_access
9
+ klass
10
+ end
11
+
5
12
  def retrieve_connection_pool
6
13
  ActiveRecord::Base.turntable_connections[name] ||=
7
14
  begin
@@ -30,7 +30,7 @@ module ActiveRecord::Turntable
30
30
  @connection_klass ||= create_connection_class
31
31
  end
32
32
 
33
- def create_connection_class
33
+ def get_or_set_connection_class
34
34
  if Connections.const_defined?(name.classify)
35
35
  klass = Connections.const_get(name.classify)
36
36
  else
@@ -38,6 +38,11 @@ module ActiveRecord::Turntable
38
38
  Connections.const_set(name.classify, klass)
39
39
  klass.abstract_class = true
40
40
  end
41
+ klass
42
+ end
43
+
44
+ def create_connection_class
45
+ klass = get_or_set_connection_class
41
46
  klass.remove_connection
42
47
  klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access
43
48
  klass
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "2.1.1"
3
+ VERSION = "2.2.0"
4
4
  end
5
5
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRecord::Turntable::Algorithm::ModuloAlgorithm do
4
+ before(:all) do
5
+ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml"))
6
+ end
7
+
8
+ context "When initialized" do
9
+ before do
10
+ @alg = ActiveRecord::Turntable::Algorithm::ModuloAlgorithm.new(ActiveRecord::Base.turntable_config[:clusters][:mod_cluster])
11
+ end
12
+
13
+ context "#calculate with 1" do
14
+ subject { @alg.calculate(1) }
15
+ it { is_expected.to eq(ActiveRecord::Base.turntable_config[:clusters][:user_cluster][:shards][1][:connection]) }
16
+ end
17
+
18
+ context "#calculate with 3" do
19
+ subject { @alg.calculate(3) }
20
+ it { is_expected.to eq(ActiveRecord::Base.turntable_config[:clusters][:user_cluster][:shards][3][:connection]) }
21
+ end
22
+
23
+ context "#calculate with 5" do
24
+ subject { @alg.calculate(5) }
25
+ it { is_expected.to eq(ActiveRecord::Base.turntable_config[:clusters][:user_cluster][:shards][0][:connection]) }
26
+ end
27
+
28
+ context "#calculate with a value that is not a number" do
29
+ it "raises ActiveRecord::Turntable::CannotSpecifyShardError" do
30
+ expect { @alg.calculate('a') }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError)
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -82,4 +82,19 @@ describe ActiveRecord::Turntable::Algorithm do
82
82
  end
83
83
  end
84
84
  end
85
+
86
+ describe ActiveRecord::Turntable::Algorithm::ModuloAlgorithm do
87
+ let(:algorithm) { ActiveRecord::Turntable::Algorithm::ModuloAlgorithm.new(ActiveRecord::Base.turntable_config[:clusters][:mod_cluster]) }
88
+ context "#calculate" do
89
+ it "called with 1 return user_shard_2" do
90
+ expect(algorithm.calculate(1)).to eq("user_shard_2")
91
+ end
92
+ it "called with 3 return user_shard_2" do
93
+ expect(algorithm.calculate(3)).to eq("user_shard_2")
94
+ end
95
+ it "called with 5 return user_shard_1" do
96
+ expect(algorithm.calculate(5)).to eq("user_shard_1")
97
+ end
98
+ end
99
+ end
85
100
  end
@@ -11,6 +11,8 @@ describe ActiveRecord::Turntable::Cluster do
11
11
  end
12
12
  let(:cluster_config) { ActiveRecord::Base.turntable_config[:clusters][:user_cluster] }
13
13
  let(:cluster) { ActiveRecord::Turntable::Cluster.new(cluster_config) }
14
+ let(:mysql_mod_cluster_config) { ActiveRecord::Base.turntable_config[:clusters][:mysql_mod_cluster] }
15
+ let(:mysql_mod_cluster) { ActiveRecord::Turntable::Cluster.new(mysql_mod_cluster_config) }
14
16
  let(:in_range_shard_key_value) { cluster_config[:shards].last[:less_than] - 1 }
15
17
  let(:out_of_range_shard_key_value) { cluster_config[:shards].last[:less_than] }
16
18
 
@@ -20,6 +22,13 @@ describe ActiveRecord::Turntable::Cluster do
20
22
  its(:shards) { should have(3).items }
21
23
  end
22
24
 
25
+ context "When initialized mysql sequencer type cluster" do
26
+ subject { mysql_mod_cluster }
27
+
28
+ its(:shards) { should have(2).items }
29
+ its(:seq) { is_expected.not_to be nil }
30
+ end
31
+
23
32
  describe "#shard_for" do
24
33
  subject { cluster.shard_for(value) }
25
34
 
@@ -32,3 +32,25 @@ test:
32
32
  less_than: 80000
33
33
  - connection: user_shard_6
34
34
  less_than: 10000000
35
+ mod_cluster:
36
+ algorithm: modulo
37
+ seq:
38
+ user_seq:
39
+ connection: turntable_user_seq_test
40
+ shards:
41
+ - connection: user_shard_1
42
+ - connection: user_shard_2
43
+ - connection: user_shard_1
44
+ - connection: user_shard_2
45
+ - connection: user_shard_3
46
+ mysql_mod_cluster:
47
+ algorithm: modulo
48
+ seq:
49
+ user_seq:
50
+ seq_type: mysql
51
+ connection: user_seq
52
+ shards:
53
+ - connection: user_shard_1
54
+ - connection: user_shard_2
55
+ - connection: user_shard_2
56
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-turntable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gussan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-26 00:00:00.000000000 Z
12
+ date: 2015-05-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -364,6 +364,7 @@ files:
364
364
  - lib/active_record/turntable/algorithm.rb
365
365
  - lib/active_record/turntable/algorithm/.gitkeep
366
366
  - lib/active_record/turntable/algorithm/base.rb
367
+ - lib/active_record/turntable/algorithm/modulo_algorithm.rb
367
368
  - lib/active_record/turntable/algorithm/range_algorithm.rb
368
369
  - lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb
369
370
  - lib/active_record/turntable/base.rb
@@ -412,6 +413,7 @@ files:
412
413
  - spec/active_record/turntable/active_record_ext/migration_spec.rb
413
414
  - spec/active_record/turntable/active_record_ext/persistence_spec.rb
414
415
  - spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb
416
+ - spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb
415
417
  - spec/active_record/turntable/algorithm/range_algorithm_spec.rb
416
418
  - spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb
417
419
  - spec/active_record/turntable/algorithm_spec.rb
@@ -482,6 +484,7 @@ test_files:
482
484
  - spec/active_record/turntable/active_record_ext/migration_spec.rb
483
485
  - spec/active_record/turntable/active_record_ext/persistence_spec.rb
484
486
  - spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb
487
+ - spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb
485
488
  - spec/active_record/turntable/algorithm/range_algorithm_spec.rb
486
489
  - spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb
487
490
  - spec/active_record/turntable/algorithm_spec.rb