ar-octopus 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +10 -2
  4. data/Appraisals +4 -0
  5. data/README.mkdn +1 -1
  6. data/gemfiles/rails51.gemfile +7 -0
  7. data/lib/octopus.rb +11 -6
  8. data/lib/octopus/collection_association.rb +9 -3
  9. data/lib/octopus/finder_methods.rb +1 -1
  10. data/lib/octopus/load_balancing/round_robin.rb +1 -0
  11. data/lib/octopus/log_subscriber.rb +6 -2
  12. data/lib/octopus/migration.rb +25 -9
  13. data/lib/octopus/model.rb +17 -25
  14. data/lib/octopus/proxy.rb +78 -279
  15. data/lib/octopus/proxy_config.rb +252 -0
  16. data/lib/octopus/relation_proxy.rb +7 -1
  17. data/lib/octopus/scope_proxy.rb +1 -1
  18. data/lib/octopus/shard_tracking.rb +2 -1
  19. data/lib/octopus/version.rb +1 -1
  20. data/spec/migrations/10_create_users_using_replication.rb +1 -1
  21. data/spec/migrations/11_add_field_in_all_slaves.rb +1 -1
  22. data/spec/migrations/12_create_users_using_block.rb +1 -1
  23. data/spec/migrations/13_create_users_using_block_and_using.rb +1 -1
  24. data/spec/migrations/14_create_users_on_shards_of_a_group_with_versions.rb +1 -1
  25. data/spec/migrations/15_create_user_on_shards_of_default_group_with_versions.rb +1 -1
  26. data/spec/migrations/1_create_users_on_master.rb +1 -1
  27. data/spec/migrations/2_create_users_on_canada.rb +1 -1
  28. data/spec/migrations/3_create_users_on_both_shards.rb +1 -1
  29. data/spec/migrations/4_create_users_on_shards_of_a_group.rb +1 -1
  30. data/spec/migrations/5_create_users_on_multiples_groups.rb +1 -1
  31. data/spec/migrations/6_raise_exception_with_invalid_shard_name.rb +1 -1
  32. data/spec/migrations/7_raise_exception_with_invalid_multiple_shard_names.rb +1 -1
  33. data/spec/migrations/8_raise_exception_with_invalid_group_name.rb +1 -1
  34. data/spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb +1 -1
  35. data/spec/octopus/association_shard_tracking_spec.rb +15 -15
  36. data/spec/octopus/load_balancing/round_robin_spec.rb +15 -0
  37. data/spec/octopus/log_subscriber_spec.rb +1 -1
  38. data/spec/octopus/model_spec.rb +34 -5
  39. data/spec/octopus/octopus_spec.rb +1 -1
  40. data/spec/octopus/proxy_spec.rb +16 -38
  41. data/spec/octopus/relation_proxy_spec.rb +4 -0
  42. data/spec/octopus/replication_spec.rb +5 -1
  43. data/spec/spec_helper.rb +2 -0
  44. data/spec/support/octopus_helper.rb +1 -2
  45. data/spec/tasks/octopus.rake_spec.rb +2 -4
  46. metadata +7 -6
  47. data/.ruby-version +0 -1
  48. data/init.rb +0 -1
  49. data/rails/init.rb +0 -1
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Octopus::LoadBalancing::RoundRobin do
4
+ it "raises an error when no shards are given" do
5
+ expect do
6
+ Octopus::LoadBalancing::RoundRobin.new([])
7
+ end.to raise_error Octopus::Exception
8
+ end
9
+
10
+ it "does not raise an error if slaves given" do
11
+ expect do
12
+ Octopus::LoadBalancing::RoundRobin.new([:stub])
13
+ end.to_not raise_error Octopus::Exception
14
+ end
15
+ end
@@ -9,7 +9,7 @@ describe Octopus::LogSubscriber, :shards => [:canada] do
9
9
  end
10
10
 
11
11
  after :each do
12
- ActiveRecord::Base.logger = nil
12
+ ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'a'))
13
13
  end
14
14
 
15
15
  it 'should add to the default logger the shard name the query was sent to' do
@@ -90,7 +90,7 @@ describe Octopus::Model do
90
90
  Octopus.using(:canada) do
91
91
  fail 'Some Exception'
92
92
  end
93
- end.to raise_error
93
+ end.to raise_error(RuntimeError)
94
94
 
95
95
  expect(ActiveRecord::Base.connection.current_shard).to eq(:master)
96
96
  end
@@ -103,7 +103,7 @@ describe Octopus::Model do
103
103
  Octopus.using(:canada) do
104
104
  fail 'Some Exception'
105
105
  end
106
- end.to raise_error
106
+ end.to raise_error(RuntimeError)
107
107
 
108
108
  expect(ActiveRecord::Base.connection.current_shard).to eq(:brazil)
109
109
  Octopus.config[:master_shard] = nil
@@ -476,6 +476,34 @@ describe Octopus::Model do
476
476
  expect(User.using(:master).count).to eq(1)
477
477
  end
478
478
 
479
+ describe "#finder methods" do
480
+ before(:each) do
481
+ @user1 = User.using(:brazil).create!(:name => 'User1')
482
+ @user2 = User.using(:brazil).create!(:name => 'User2')
483
+ @user3 = User.using(:brazil).create!(:name => 'User3')
484
+ end
485
+
486
+ it "#find_each should work" do
487
+ result_array = []
488
+
489
+ User.using(:brazil).where("name is not NULL").find_each do |user|
490
+ result_array << user
491
+ end
492
+
493
+ expect(result_array).to eq([@user1, @user2, @user3])
494
+ end
495
+
496
+ it "#find_in_batches, should work" do
497
+ result_array = []
498
+
499
+ User.using(:brazil).where("name is not NULL").find_in_batches(batch_size: 1) do |user|
500
+ result_array << user
501
+ end
502
+
503
+ expect(result_array).to eq([[@user1], [@user2], [@user3]])
504
+ end
505
+ end
506
+
479
507
  describe 'deleting a record' do
480
508
  before(:each) do
481
509
  @user = User.using(:brazil).create!(:name => 'User1')
@@ -665,20 +693,21 @@ describe Octopus::Model do
665
693
  it 'should work correctly when using validations' do
666
694
  @key = Keyboard.create!(:name => 'Key')
667
695
  expect { Keyboard.using(:brazil).create!(:name => 'Key') }.not_to raise_error
668
- expect { Keyboard.create!(:name => 'Key') }.to raise_error
696
+ expect { Keyboard.create!(:name => 'Key') }.to raise_error(ActiveRecord::RecordInvalid)
669
697
  end
670
698
 
671
699
  it 'should work correctly when using validations with using syntax' do
672
700
  @key = Keyboard.using(:brazil).create!(:name => 'Key')
673
701
  expect { Keyboard.create!(:name => 'Key') }.not_to raise_error
674
- expect { Keyboard.using(:brazil).create!(:name => 'Key') }.to raise_error
702
+ expect { Keyboard.using(:brazil).create!(:name => 'Key') }
703
+ .to raise_error(ActiveRecord::RecordInvalid)
675
704
  end
676
705
  end
677
706
 
678
707
  describe '#replicated_model method' do
679
708
  it 'should be replicated' do
680
709
  OctopusHelper.using_environment :production_replicated do
681
- expect(ActiveRecord::Base.connection_proxy.instance_variable_get(:@replicated)).to be true
710
+ expect(ActiveRecord::Base.connection_proxy.replicated).to be true
682
711
  end
683
712
  end
684
713
 
@@ -37,7 +37,7 @@ describe Octopus, :shards => [] do
37
37
  end
38
38
 
39
39
  it 'should permit users to configure shards on initializer files, instead of on a yml file.' do
40
- expect { User.using(:crazy_shard).create!(:name => 'Joaquim') }.to raise_error
40
+ expect { User.using(:crazy_shard).create!(:name => 'Joaquim') }.to raise_error(RuntimeError)
41
41
 
42
42
  Octopus.setup do |config|
43
43
  config.shards = { :crazy_shard => { :adapter => 'mysql2', :database => 'octopus_shard_5', :username => 'root', :password => '' } }
@@ -6,10 +6,10 @@ describe Octopus::Proxy do
6
6
  describe 'creating a new instance', :shards => [] do
7
7
  it 'should initialize all shards and groups' do
8
8
  # FIXME: Don't test implementation details
9
- expect(proxy.instance_variable_get(:@shards)).to include('canada', 'brazil', 'master', 'sqlite_shard', 'russia', 'alone_shard',
9
+ expect(proxy.shards).to include('canada', 'brazil', 'master', 'sqlite_shard', 'russia', 'alone_shard',
10
10
  'aug2009', 'postgresql_shard', 'aug2010', 'aug2011')
11
11
 
12
- expect(proxy.instance_variable_get(:@shards)).to include('protocol_shard')
12
+ expect(proxy.shards).to include('protocol_shard')
13
13
 
14
14
  expect(proxy.has_group?('country_shards')).to be true
15
15
  expect(proxy.shards_for_group('country_shards')).to include(:canada, :brazil, :russia)
@@ -23,23 +23,17 @@ describe Octopus::Proxy do
23
23
  end
24
24
 
25
25
  it 'should initialize replicated attribute as false' do
26
- expect(proxy.instance_variable_get(:@replicated)).to be_falsey
26
+ expect(proxy.replicated).to be_falsey
27
27
  end
28
28
 
29
- it 'should work with thiking sphinx' do
30
- config = proxy.instance_variable_get(:@config)
29
+ it 'should work with thinking sphinx' do
30
+ config = proxy.config
31
31
  expect(config[:adapter]).to eq('mysql2')
32
32
  expect(config[:database]).to eq('octopus_shard_1')
33
33
  expect(config[:username]).to eq('root')
34
34
  end
35
35
 
36
- it 'should create a set with all adapters, to ensure that is needed to clean the table name.' do
37
- adapters = proxy.instance_variable_get(:@adapters)
38
- expect(adapters).to be_kind_of(Set)
39
- expect(adapters.to_a).to match_array(%w(sqlite3 mysql2 postgresql))
40
- end
41
-
42
- unless Octopus.rails5?
36
+ unless Octopus.rails50? || Octopus.rails51?
43
37
  it 'should respond correctly to respond_to?(:pk_and_sequence_for)' do
44
38
  expect(proxy.respond_to?(:pk_and_sequence_for)).to be true
45
39
  end
@@ -63,22 +57,6 @@ describe Octopus::Proxy do
63
57
  end
64
58
  end
65
59
 
66
- describe '#should_clean_table_name?' do
67
- it 'should return true when you have a environment with multiple database types' do
68
- expect(proxy.should_clean_table_name?).to be true
69
- end
70
-
71
- context 'when using a environment with a single table name' do
72
- before(:each) do
73
- OctopusHelper.octopus_env = 'production_replicated'
74
- end
75
-
76
- it 'should return false' do
77
- expect(proxy.should_clean_table_name?).to be false
78
- end
79
- end
80
- end
81
-
82
60
  describe 'should raise error if you have duplicated shard names' do
83
61
  before(:each) do
84
62
  OctopusHelper.octopus_env = 'production_raise_error'
@@ -95,11 +73,11 @@ describe Octopus::Proxy do
95
73
  end
96
74
 
97
75
  it 'should initialize just the master shard' do
98
- expect(proxy.instance_variable_get(:@shards).keys).to eq(['master'])
76
+ expect(proxy.shards.keys).to eq(['master'])
99
77
  end
100
78
 
101
79
  it 'should not initialize replication' do
102
- expect(proxy.instance_variable_get(:@replicated)).to be_nil
80
+ expect(proxy.replicated).to be_nil
103
81
  end
104
82
  end
105
83
  end
@@ -110,11 +88,11 @@ describe Octopus::Proxy do
110
88
  end
111
89
 
112
90
  it 'should have the replicated attribute as true' do
113
- expect(proxy.instance_variable_get(:@replicated)).to be true
91
+ expect(proxy.replicated).to be true
114
92
  end
115
93
 
116
94
  it 'should initialize the list of shards' do
117
- expect(proxy.instance_variable_get(:@slaves_list)).to eq(%w(slave1 slave2 slave3 slave4))
95
+ expect(proxy.slaves_list).to eq(%w(slave1 slave2 slave3 slave4))
118
96
  end
119
97
  end
120
98
 
@@ -137,7 +115,7 @@ describe Octopus::Proxy do
137
115
  Octopus.instance_variable_set(:@environments, nil)
138
116
  Octopus.config
139
117
 
140
- expect(proxy.instance_variable_get(:@replicated)).to be true
118
+ expect(proxy.replicated).to be true
141
119
  expect(Octopus.environments).to eq(%w(staging production))
142
120
  end
143
121
 
@@ -147,7 +125,7 @@ describe Octopus::Proxy do
147
125
  Octopus.instance_variable_set(:@environments, nil)
148
126
  Octopus.config
149
127
 
150
- expect(proxy.instance_variable_get(:@shards).keys.to_set).to eq(Set.new(%w(slave1 slave2 master)))
128
+ expect(proxy.shards.keys.to_set).to eq(Set.new(%w(slave1 slave2 master)))
151
129
  end
152
130
 
153
131
  it 'should initialize correctly the shard octopus_shard value for logging' do
@@ -156,7 +134,7 @@ describe Octopus::Proxy do
156
134
  Octopus.instance_variable_set(:@environments, nil)
157
135
  Octopus.config
158
136
 
159
- expect(proxy.instance_variable_get(:@shards)['slave1'].spec.config).to have_key :octopus_shard
137
+ expect(proxy.shards['slave1'].spec.config).to have_key :octopus_shard
160
138
  end
161
139
 
162
140
  it 'should initialize correctly the shards for the production environment' do
@@ -165,7 +143,7 @@ describe Octopus::Proxy do
165
143
  Octopus.instance_variable_set(:@environments, nil)
166
144
  Octopus.config
167
145
 
168
- expect(proxy.instance_variable_get(:@shards).keys.to_set).to eq(Set.new(%w(slave3 slave4 master)))
146
+ expect(proxy.shards.keys.to_set).to eq(Set.new(%w(slave3 slave4 master)))
169
147
  end
170
148
 
171
149
  describe 'using the master connection', :shards => [:russia, :master] do
@@ -234,12 +212,12 @@ describe Octopus::Proxy do
234
212
 
235
213
  describe 'should return the connection based on shard_name' do
236
214
  it 'when current_shard is empty' do
237
- expect(proxy.select_connection).to eq(proxy.instance_variable_get(:@shards)[:master].connection)
215
+ expect(proxy.select_connection).to eq(proxy.shards[:master].connection)
238
216
  end
239
217
 
240
218
  it 'when current_shard is a single shard' do
241
219
  proxy.current_shard = :canada
242
- expect(proxy.select_connection).to eq(proxy.instance_variable_get(:@shards)[:canada].connection)
220
+ expect(proxy.select_connection).to eq(proxy.shards[:canada].connection)
243
221
  end
244
222
  end
245
223
  end
@@ -38,6 +38,10 @@ describe Octopus::RelationProxy do
38
38
  end
39
39
  end
40
40
 
41
+ it "can deliver methods in ActiveRecord::Batches correctly" do
42
+ expect { @relation.find_each(&:inspect) }.not_to raise_error
43
+ end
44
+
41
45
  context 'under Rails 4' do
42
46
  it 'is an Octopus::RelationProxy' do
43
47
  expect{@relation.ar_relation}.not_to raise_error
@@ -42,7 +42,11 @@ describe 'when the database is replicated' do
42
42
  expect(Cat.find(cat3.id).id).to eq(cat3.id)
43
43
  expect(Cat.find(cat3.id).id).to eq(cat3.id)
44
44
 
45
- expect(counter.query_count).to eq(14)
45
+ # Rails 5.1 count the cached queries as regular queries.
46
+ # TODO: How we can verify if the queries are using cache on Rails 5.1? - @thiagopradi
47
+ expected_records = Octopus.rails51? ? 19 : 14
48
+
49
+ expect(counter.query_count).to eq(expected_records)
46
50
  end
47
51
  end
48
52
  end
@@ -5,6 +5,8 @@ require 'octopus'
5
5
 
6
6
  Octopus.instance_variable_set(:@directory, File.dirname(__FILE__))
7
7
 
8
+ BaseOctopusMigrationClass = (Octopus.rails4? ? ActiveRecord::Migration : ActiveRecord::Migration[ActiveRecord::VERSION::STRING[0..2]])
9
+
8
10
  # Requires supporting files with custom matchers and macros, etc,
9
11
  # in ./support/ and its subdirectories.
10
12
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -1,7 +1,7 @@
1
1
  module OctopusHelper
2
2
  def self.clean_all_shards(shards)
3
3
  if shards.nil?
4
- shards = BlankModel.using(:master).connection.instance_variable_get(:@shards).keys
4
+ shards = BlankModel.using(:master).connection.shards.keys
5
5
  end
6
6
 
7
7
  shards.each do |shard_symbol|
@@ -23,7 +23,6 @@ module OctopusHelper
23
23
  Thread.current['octopus.current_group'] = nil
24
24
  Thread.current['octopus.current_slave_group'] = nil
25
25
  Thread.current['octopus.block'] = nil
26
- Thread.current['octopus.last_current_shard'] = nil
27
26
 
28
27
  ActiveRecord::Base.class_variable_set(:@@connection_proxy, nil)
29
28
  end
@@ -24,10 +24,8 @@ describe 'octopus.rake' do
24
24
 
25
25
  Rake::Task['octopus:copy_schema_versions'].invoke
26
26
 
27
- # Skip SQLite shard for now - not sure why this test is failing.
28
- # TODO - Verify this test in the future.
29
- ActiveRecord::Base.connection.shard_names.reject { |sh_name| sh_name == 'sqlite_shard' }.each do |shard_name|
30
- expect(Octopus.using(shard_name) { ActiveRecord::Migrator.get_all_versions }).to eq([1, 2, 3])
27
+ ActiveRecord::Base.connection.shard_names.each do |shard_name|
28
+ expect(Octopus.using(shard_name) { ActiveRecord::SchemaMigration.all.pluck(:version).map(&:to_i).sort }).to eq([1, 2, 3])
31
29
  end
32
30
  end
33
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-octopus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thiago Pradi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-12-08 00:00:00.000000000 Z
13
+ date: 2017-07-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -167,7 +167,6 @@ files:
167
167
  - ".rspec"
168
168
  - ".rubocop.yml"
169
169
  - ".rubocop_todo.yml"
170
- - ".ruby-version"
171
170
  - ".travis.yml"
172
171
  - Appraisals
173
172
  - Gemfile
@@ -179,7 +178,7 @@ files:
179
178
  - gemfiles/rails41.gemfile
180
179
  - gemfiles/rails42.gemfile
181
180
  - gemfiles/rails5.gemfile
182
- - init.rb
181
+ - gemfiles/rails51.gemfile
183
182
  - lib/ar-octopus.rb
184
183
  - lib/octopus.rb
185
184
  - lib/octopus/abstract_adapter.rb
@@ -197,6 +196,7 @@ files:
197
196
  - lib/octopus/model.rb
198
197
  - lib/octopus/persistence.rb
199
198
  - lib/octopus/proxy.rb
199
+ - lib/octopus/proxy_config.rb
200
200
  - lib/octopus/railtie.rb
201
201
  - lib/octopus/relation_proxy.rb
202
202
  - lib/octopus/scope_proxy.rb
@@ -207,7 +207,6 @@ files:
207
207
  - lib/octopus/slave_group.rb
208
208
  - lib/octopus/version.rb
209
209
  - lib/tasks/octopus.rake
210
- - rails/init.rb
211
210
  - sample_app/.gitignore
212
211
  - sample_app/.rspec
213
212
  - sample_app/Gemfile
@@ -301,6 +300,7 @@ files:
301
300
  - spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb
302
301
  - spec/octopus/association_shard_tracking_spec.rb
303
302
  - spec/octopus/collection_proxy_spec.rb
303
+ - spec/octopus/load_balancing/round_robin_spec.rb
304
304
  - spec/octopus/log_subscriber_spec.rb
305
305
  - spec/octopus/migration_spec.rb
306
306
  - spec/octopus/model_spec.rb
@@ -344,7 +344,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
344
344
  version: '0'
345
345
  requirements: []
346
346
  rubyforge_project:
347
- rubygems_version: 2.4.5.1
347
+ rubygems_version: 2.2.2
348
348
  signing_key:
349
349
  specification_version: 4
350
350
  summary: Easy Database Sharding for ActiveRecord
@@ -367,6 +367,7 @@ test_files:
367
367
  - spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb
368
368
  - spec/octopus/association_shard_tracking_spec.rb
369
369
  - spec/octopus/collection_proxy_spec.rb
370
+ - spec/octopus/load_balancing/round_robin_spec.rb
370
371
  - spec/octopus/log_subscriber_spec.rb
371
372
  - spec/octopus/migration_spec.rb
372
373
  - spec/octopus/model_spec.rb
@@ -1 +0,0 @@
1
- 2.1.5
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'rails', 'init')
@@ -1 +0,0 @@
1
- require 'octopus'