ar-octopus 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -8
- data/Appraisals +4 -8
- data/README.mkdn +6 -1
- data/Rakefile +1 -0
- data/ar-octopus.gemspec +4 -4
- data/gemfiles/rails42.gemfile +2 -2
- data/gemfiles/rails5.gemfile +1 -1
- data/gemfiles/rails51.gemfile +1 -1
- data/gemfiles/{rails4.gemfile → rails52.gemfile} +2 -2
- data/lib/octopus.rb +13 -13
- data/lib/octopus/association_shard_tracking.rb +1 -1
- data/lib/octopus/collection_association.rb +1 -1
- data/lib/octopus/migration.rb +102 -61
- data/lib/octopus/model.rb +8 -12
- data/lib/octopus/proxy.rb +32 -11
- data/lib/octopus/proxy_config.rb +7 -8
- data/lib/octopus/query_cache_for_shards.rb +24 -0
- data/lib/octopus/relation_proxy.rb +10 -1
- data/lib/octopus/scope_proxy.rb +1 -1
- data/lib/octopus/version.rb +1 -1
- data/spec/octopus/association_shard_tracking_spec.rb +314 -0
- data/spec/octopus/migration_spec.rb +29 -14
- data/spec/octopus/model_spec.rb +20 -3
- data/spec/octopus/proxy_spec.rb +1 -1
- data/spec/octopus/query_cache_for_shards_spec.rb +40 -0
- data/spec/octopus/replication_spec.rb +57 -2
- data/spec/octopus/scope_proxy_spec.rb +21 -0
- data/spec/support/octopus_helper.rb +13 -4
- metadata +19 -12
- data/gemfiles/rails41.gemfile +0 -7
- data/lib/octopus/has_and_belongs_to_many_association.rb +0 -9
data/spec/octopus/model_spec.rb
CHANGED
@@ -306,8 +306,13 @@ describe Octopus::Model do
|
|
306
306
|
|
307
307
|
describe 'using a postgresql shard' do
|
308
308
|
it 'should update the Arel Engine' do
|
309
|
-
|
310
|
-
|
309
|
+
if Octopus.atleast_rails52?
|
310
|
+
expect(User.using(:postgresql_shard).connection.adapter_name).to eq('PostgreSQL')
|
311
|
+
expect(User.using(:alone_shard).connection.adapter_name).to eq('Mysql2')
|
312
|
+
else
|
313
|
+
expect(User.using(:postgresql_shard).arel_engine.connection.adapter_name).to eq('PostgreSQL')
|
314
|
+
expect(User.using(:alone_shard).arel_engine.connection.adapter_name).to eq('Mysql2')
|
315
|
+
end
|
311
316
|
end
|
312
317
|
|
313
318
|
it 'should works with writes and reads' do
|
@@ -393,6 +398,18 @@ describe Octopus::Model do
|
|
393
398
|
expect(User.using(:master).maximum(:number)).to eq(12)
|
394
399
|
end
|
395
400
|
|
401
|
+
it 'sum' do
|
402
|
+
u = User.using(:brazil).create!(:name => 'Teste', :number => 11)
|
403
|
+
v = User.using(:master).create!(:name => 'Teste', :number => 12)
|
404
|
+
|
405
|
+
expect(User.using(:master).sum(:number)).to eq(12)
|
406
|
+
expect(User.using(:brazil).sum(:number)).to eq(11)
|
407
|
+
|
408
|
+
expect(User.where(id: v.id).sum(:number)).to eq(12)
|
409
|
+
expect(User.using(:brazil).where(id: u.id).sum(:number)).to eq(11)
|
410
|
+
expect(User.using(:master).where(id: v.id).sum(:number)).to eq(12)
|
411
|
+
end
|
412
|
+
|
396
413
|
describe 'any?' do
|
397
414
|
before { User.using(:brazil).create!(:name => 'User1') }
|
398
415
|
|
@@ -747,7 +764,7 @@ describe Octopus::Model do
|
|
747
764
|
|
748
765
|
replicated_cat = User.find_by_name 'Thiago'
|
749
766
|
|
750
|
-
expect(replicated_cat.current_shard.to_s).to match(/
|
767
|
+
expect(replicated_cat.current_shard.to_s).to match(/master/)
|
751
768
|
end
|
752
769
|
end
|
753
770
|
end
|
data/spec/octopus/proxy_spec.rb
CHANGED
@@ -33,7 +33,7 @@ describe Octopus::Proxy do
|
|
33
33
|
expect(config[:username]).to eq("#{ENV['MYSQL_USER'] || 'root'}")
|
34
34
|
end
|
35
35
|
|
36
|
-
unless Octopus.rails50? || Octopus.rails51?
|
36
|
+
unless Octopus.rails50? || Octopus.rails51?|| Octopus.rails52?
|
37
37
|
it 'should respond correctly to respond_to?(:pk_and_sequence_for)' do
|
38
38
|
expect(proxy.respond_to?(:pk_and_sequence_for)).to be true
|
39
39
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
unless Octopus.rails4? || Octopus.rails50?
|
4
|
+
describe Octopus::ConnectionPool::QueryCacheForShards do
|
5
|
+
subject(:query_cache_on_shard) { ActiveRecord::Base.using(:brazil).connection.query_cache_enabled }
|
6
|
+
|
7
|
+
context 'Octopus enabled' do
|
8
|
+
context 'when query cache is enabled on the primary connection_pool' do
|
9
|
+
before { ActiveRecord::Base.connection_pool.enable_query_cache! }
|
10
|
+
it { is_expected.to be true }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when query cache is disabled on the primary connection_pool' do
|
14
|
+
before { ActiveRecord::Base.connection_pool.disable_query_cache! }
|
15
|
+
it { is_expected.to be false }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'Octopus disabled' do
|
20
|
+
before do
|
21
|
+
Rails = double
|
22
|
+
allow(Rails).to receive(:env).and_return('staging')
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
Object.send(:remove_const, :Rails)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when query cache is enabled on the primary connection_pool' do
|
30
|
+
before { ActiveRecord::Base.connection_pool.enable_query_cache! }
|
31
|
+
it { is_expected.to be true }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when query cache is disabled on the primary connection_pool' do
|
35
|
+
before { ActiveRecord::Base.connection_pool.disable_query_cache! }
|
36
|
+
it { is_expected.to be false }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,6 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'when the database is replicated' do
|
4
|
+
let(:slave_pool) do
|
5
|
+
ActiveRecord::Base.connection_proxy.shards['slave1']
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:slave_connection) do
|
9
|
+
slave_pool.connection
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:master_pool) do
|
13
|
+
ActiveRecord::Base.connection_proxy.shards['master']
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:master_connection) do
|
17
|
+
master_pool.connection
|
18
|
+
end
|
19
|
+
|
4
20
|
it 'should send all writes/reads queries to master when you have a non replicated model' do
|
5
21
|
OctopusHelper.using_environment :production_replicated do
|
6
22
|
u = User.create!(:name => 'Replicated')
|
@@ -26,10 +42,49 @@ describe 'when the database is replicated' do
|
|
26
42
|
end
|
27
43
|
end
|
28
44
|
|
45
|
+
context 'when updating model' do
|
46
|
+
it 'should send writes to master' do
|
47
|
+
OctopusHelper.using_environment :replicated_with_one_slave do
|
48
|
+
Cat.using(:slave1).create!(:name => 'Cat')
|
49
|
+
cat = Cat.find_by_name('Cat')
|
50
|
+
cat.name = 'New name'
|
51
|
+
|
52
|
+
expect(master_connection).to receive(:update).and_call_original
|
53
|
+
|
54
|
+
cat.save!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when querying' do
|
60
|
+
it 'Reads from slave' do
|
61
|
+
OctopusHelper.using_environment :replicated_with_one_slave do
|
62
|
+
expect(master_connection).not_to receive(:select)
|
63
|
+
|
64
|
+
Cat.where(:name => 'Catman2').first
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'When record is read from slave' do
|
70
|
+
it 'Should write associations to master' do
|
71
|
+
OctopusHelper.using_environment :replicated_with_one_slave do
|
72
|
+
client = Client.using(:slave1).create!(:name => 'Client')
|
73
|
+
|
74
|
+
client = Client.find(client.id)
|
75
|
+
|
76
|
+
expect(master_connection).to receive(:insert).and_call_original
|
77
|
+
|
78
|
+
client.items.create!(:name => 'Item')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
29
84
|
describe 'When enabling the query cache' do
|
30
85
|
include_context 'with query cache enabled' do
|
31
86
|
it 'should do the queries with cache' do
|
32
|
-
OctopusHelper.using_environment :replicated_with_one_slave
|
87
|
+
OctopusHelper.using_environment :replicated_with_one_slave do
|
33
88
|
cat1 = Cat.using(:master).create!(:name => 'Master Cat 1')
|
34
89
|
_ct2 = Cat.using(:master).create!(:name => 'Master Cat 2')
|
35
90
|
expect(Cat.using(:master).find(cat1.id)).to eq(cat1)
|
@@ -44,7 +99,7 @@ describe 'when the database is replicated' do
|
|
44
99
|
|
45
100
|
# Rails 5.1 count the cached queries as regular queries.
|
46
101
|
# TODO: How we can verify if the queries are using cache on Rails 5.1? - @thiagopradi
|
47
|
-
expected_records = Octopus.rails51? ? 19 : 14
|
102
|
+
expected_records = Octopus.rails51? || Octopus.rails52? ? 19 : 14
|
48
103
|
|
49
104
|
expect(counter.query_count).to eq(expected_records)
|
50
105
|
end
|
@@ -73,4 +73,25 @@ describe Octopus::ScopeProxy do
|
|
73
73
|
expect(cloned_object.object_id).not_to eq(user.object_id)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
context 'When iterated with Enumerable methods' do
|
78
|
+
before(:each) do
|
79
|
+
User.using(:brazil).create!(:name => 'Evan', :number => 1)
|
80
|
+
User.using(:brazil).create!(:name => 'Evan', :number => 2)
|
81
|
+
User.using(:brazil).create!(:name => 'Evan', :number => 3)
|
82
|
+
@evans = User.using(:brazil).where(:name => 'Evan')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'allows each method' do
|
86
|
+
expect(@evans.each.count).to eq(3)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'allows each_with_index method' do
|
90
|
+
expect(@evans.each_with_index.to_a.flatten.count).to eq(6)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'allows map method' do
|
94
|
+
expect(@evans.map(&:number)).to eq([1, 2, 3])
|
95
|
+
end
|
96
|
+
end
|
76
97
|
end
|
@@ -8,12 +8,12 @@ module OctopusHelper
|
|
8
8
|
%w(schema_migrations users clients cats items keyboards computers permissions_roles roles permissions assignments projects programmers yummy adverts).each do |tables|
|
9
9
|
BlankModel.using(shard_symbol).connection.execute("DELETE FROM #{tables}")
|
10
10
|
end
|
11
|
-
|
12
11
|
if shard_symbol == 'alone_shard'
|
13
12
|
%w(mmorpg_players weapons skills).each do |table|
|
14
13
|
BlankModel.using(shard_symbol).connection.execute("DELETE FROM #{table}")
|
15
14
|
end
|
16
15
|
end
|
16
|
+
BlankModel.using(:master).connection.shards[shard_symbol].disconnect if Octopus.atleast_rails50?
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -29,12 +29,21 @@ module OctopusHelper
|
|
29
29
|
|
30
30
|
def self.migrating_to_version(version, &_block)
|
31
31
|
migrations_root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'migrations'))
|
32
|
-
|
32
|
+
|
33
33
|
begin
|
34
|
-
|
34
|
+
migrate_to_version(:up, migrations_root, version)
|
35
35
|
yield
|
36
36
|
ensure
|
37
|
-
|
37
|
+
migrate_to_version(:down, migrations_root, version)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.migrate_to_version(direction, root, version)
|
42
|
+
if Octopus.atleast_rails52?
|
43
|
+
migrations = ActiveRecord::MigrationContext.new(root).migrations.select {|mig| version == mig.version }
|
44
|
+
ActiveRecord::Migrator.new(direction, migrations, version).run
|
45
|
+
else
|
46
|
+
ActiveRecord::Migrator.run(direction, root, version)
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
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.
|
4
|
+
version: 0.10.0
|
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: 2018-
|
13
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -18,28 +18,28 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 4.
|
21
|
+
version: 4.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 4.
|
28
|
+
version: 4.2.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: activesupport
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 4.
|
35
|
+
version: 4.2.0
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 4.
|
42
|
+
version: 4.2.0
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: appraisal
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,16 +58,22 @@ dependencies:
|
|
58
58
|
name: mysql2
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- - "
|
61
|
+
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: 0.3.18
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.5'
|
64
67
|
type: :development
|
65
68
|
prerelease: false
|
66
69
|
version_requirements: !ruby/object:Gem::Requirement
|
67
70
|
requirements:
|
68
|
-
- - "
|
71
|
+
- - ">="
|
69
72
|
- !ruby/object:Gem::Version
|
70
73
|
version: 0.3.18
|
74
|
+
- - "<"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.5'
|
71
77
|
- !ruby/object:Gem::Dependency
|
72
78
|
name: pg
|
73
79
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,11 +180,10 @@ files:
|
|
174
180
|
- Rakefile
|
175
181
|
- TODO.txt
|
176
182
|
- ar-octopus.gemspec
|
177
|
-
- gemfiles/rails4.gemfile
|
178
|
-
- gemfiles/rails41.gemfile
|
179
183
|
- gemfiles/rails42.gemfile
|
180
184
|
- gemfiles/rails5.gemfile
|
181
185
|
- gemfiles/rails51.gemfile
|
186
|
+
- gemfiles/rails52.gemfile
|
182
187
|
- lib/ar-octopus.rb
|
183
188
|
- lib/octopus.rb
|
184
189
|
- lib/octopus/abstract_adapter.rb
|
@@ -188,7 +193,6 @@ files:
|
|
188
193
|
- lib/octopus/collection_proxy.rb
|
189
194
|
- lib/octopus/exception.rb
|
190
195
|
- lib/octopus/finder_methods.rb
|
191
|
-
- lib/octopus/has_and_belongs_to_many_association.rb
|
192
196
|
- lib/octopus/load_balancing.rb
|
193
197
|
- lib/octopus/load_balancing/round_robin.rb
|
194
198
|
- lib/octopus/log_subscriber.rb
|
@@ -197,6 +201,7 @@ files:
|
|
197
201
|
- lib/octopus/persistence.rb
|
198
202
|
- lib/octopus/proxy.rb
|
199
203
|
- lib/octopus/proxy_config.rb
|
204
|
+
- lib/octopus/query_cache_for_shards.rb
|
200
205
|
- lib/octopus/railtie.rb
|
201
206
|
- lib/octopus/relation_proxy.rb
|
202
207
|
- lib/octopus/result_patch.rb
|
@@ -307,6 +312,7 @@ files:
|
|
307
312
|
- spec/octopus/model_spec.rb
|
308
313
|
- spec/octopus/octopus_spec.rb
|
309
314
|
- spec/octopus/proxy_spec.rb
|
315
|
+
- spec/octopus/query_cache_for_shards_spec.rb
|
310
316
|
- spec/octopus/relation_proxy_spec.rb
|
311
317
|
- spec/octopus/replicated_slave_grouped_spec.rb
|
312
318
|
- spec/octopus/replication_spec.rb
|
@@ -337,7 +343,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
337
343
|
requirements:
|
338
344
|
- - ">="
|
339
345
|
- !ruby/object:Gem::Version
|
340
|
-
version: 2.
|
346
|
+
version: 2.2.0
|
341
347
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
342
348
|
requirements:
|
343
349
|
- - ">="
|
@@ -374,6 +380,7 @@ test_files:
|
|
374
380
|
- spec/octopus/model_spec.rb
|
375
381
|
- spec/octopus/octopus_spec.rb
|
376
382
|
- spec/octopus/proxy_spec.rb
|
383
|
+
- spec/octopus/query_cache_for_shards_spec.rb
|
377
384
|
- spec/octopus/relation_proxy_spec.rb
|
378
385
|
- spec/octopus/replicated_slave_grouped_spec.rb
|
379
386
|
- spec/octopus/replication_spec.rb
|
data/gemfiles/rails41.gemfile
DELETED