switchman 0.0.1
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 +7 -0
- data/Rakefile +30 -0
- data/app/models/switchman/shard.rb +502 -0
- data/db/migrate/20130328212039_create_switchman_shards.rb +9 -0
- data/db/migrate/20130328224244_create_default_shard.rb +9 -0
- data/lib/switchman.rb +9 -0
- data/lib/switchman/active_record/abstract_adapter.rb +11 -0
- data/lib/switchman/active_record/association.rb +108 -0
- data/lib/switchman/active_record/attribute_methods.rb +104 -0
- data/lib/switchman/active_record/base.rb +95 -0
- data/lib/switchman/active_record/calculations.rb +63 -0
- data/lib/switchman/active_record/connection_handler.rb +147 -0
- data/lib/switchman/active_record/connection_pool.rb +117 -0
- data/lib/switchman/active_record/finder_methods.rb +25 -0
- data/lib/switchman/active_record/log_subscriber.rb +43 -0
- data/lib/switchman/active_record/postgresql_adapter.rb +13 -0
- data/lib/switchman/active_record/query_cache.rb +12 -0
- data/lib/switchman/active_record/query_methods.rb +184 -0
- data/lib/switchman/active_record/relation.rb +69 -0
- data/lib/switchman/cache_extensions.rb +12 -0
- data/lib/switchman/connection_pool_proxy.rb +62 -0
- data/lib/switchman/database_server.rb +197 -0
- data/lib/switchman/default_shard.rb +28 -0
- data/lib/switchman/engine.rb +91 -0
- data/lib/switchman/r_spec_helper.rb +124 -0
- data/lib/switchman/shackles.rb +34 -0
- data/lib/switchman/test_helper.rb +65 -0
- data/lib/switchman/version.rb +3 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/models/appendage.rb +24 -0
- data/spec/dummy/app/models/digit.rb +9 -0
- data/spec/dummy/app/models/feature.rb +5 -0
- data/spec/dummy/app/models/mirror_user.rb +5 -0
- data/spec/dummy/app/models/user.rb +23 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +17 -0
- data/spec/dummy/config/database.yml.example +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/routes.rb +8 -0
- data/spec/dummy/db/migrate/20130403132607_create_users.rb +10 -0
- data/spec/dummy/db/migrate/20130411202442_create_appendages.rb +10 -0
- data/spec/dummy/db/migrate/20130411202551_create_mirror_users.rb +9 -0
- data/spec/dummy/db/migrate/20131022202028_create_digits.rb +10 -0
- data/spec/dummy/db/migrate/20131206172923_create_features.rb +12 -0
- data/spec/dummy/db/schema.rb +57 -0
- data/spec/dummy/log/development.log +504 -0
- data/spec/dummy/log/test.log +29907 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/tmp/cache/2E2/830/shard%2F2 +0 -0
- data/spec/dummy/tmp/cache/2E3/840/shard%2F3 +0 -0
- data/spec/dummy/tmp/cache/313/970/shard%2F30 +0 -0
- data/spec/dummy/tmp/cache/314/980/shard%2F31 +0 -0
- data/spec/dummy/tmp/cache/316/980/shard%2F15 +1 -0
- data/spec/dummy/tmp/cache/316/9D0/shard%2F60 +0 -0
- data/spec/dummy/tmp/cache/317/990/shard%2F16 +0 -0
- data/spec/dummy/tmp/cache/317/9C0/shard%2F43 +1 -0
- data/spec/dummy/tmp/cache/317/9E0/shard%2F61 +0 -0
- data/spec/dummy/tmp/cache/318/9A0/shard%2F17 +0 -0
- data/spec/dummy/tmp/cache/318/9D0/shard%2F44 +0 -0
- data/spec/dummy/tmp/cache/318/9F0/shard%2F62 +1 -0
- data/spec/dummy/tmp/cache/319/9E0/shard%2F45 +0 -0
- data/spec/dummy/tmp/cache/319/9F0/shard%2F54 +1 -0
- data/spec/dummy/tmp/cache/319/A10/shard%2F72 +1 -0
- data/spec/dummy/tmp/cache/319/A30/shard%2F90 +0 -0
- data/spec/dummy/tmp/cache/31B/9E0/shard%2F29 +1 -0
- data/spec/dummy/tmp/cache/321/AA0/shard%2F89 +0 -0
- data/spec/dummy/tmp/cache/322/AC0/shard%2F99 +1 -0
- data/spec/dummy/tmp/cache/344/D70/shard%2F103 +1 -0
- data/spec/dummy/tmp/cache/345/D80/shard%2F104 +0 -0
- data/spec/dummy/tmp/cache/345/DB0/shard%2F131 +1 -0
- data/spec/dummy/tmp/cache/345/DC0/shard%2F140 +0 -0
- data/spec/dummy/tmp/cache/346/D90/shard%2F105 +0 -0
- data/spec/dummy/tmp/cache/346/DB0/shard%2F123 +0 -0
- data/spec/dummy/tmp/cache/346/DD0/shard%2F222 +1 -0
- data/spec/dummy/tmp/cache/346/DE0/shard%2F150 +0 -0
- data/spec/dummy/tmp/cache/346/DF0/shard%2F240 +1 -0
- data/spec/dummy/tmp/cache/347/DA0/shard%2F106 +1 -0
- data/spec/dummy/tmp/cache/347/DC0/shard%2F124 +0 -0
- data/spec/dummy/tmp/cache/347/DC0/shard%2F205 +1 -0
- data/spec/dummy/tmp/cache/347/E10/shard%2F250 +1 -0
- data/spec/dummy/tmp/cache/348/DF0/shard%2F143 +1 -0
- data/spec/dummy/tmp/cache/348/DF0/shard%2F224 +1 -0
- data/spec/dummy/tmp/cache/348/E10/shard%2F161 +1 -0
- data/spec/dummy/tmp/cache/349/DD0/shard%2F117 +1 -0
- data/spec/dummy/tmp/cache/349/E40/shard%2F180 +1 -0
- data/spec/dummy/tmp/cache/34A/DF0/shard%2F127 +1 -0
- data/spec/dummy/tmp/cache/34A/DF0/shard%2F208 +1 -0
- data/spec/dummy/tmp/cache/34A/E10/shard%2F145 +1 -0
- data/spec/dummy/tmp/cache/34A/E60/shard%2F190 +1 -0
- data/spec/dummy/tmp/cache/34B/E30/shard%2F155 +1 -0
- data/spec/dummy/tmp/cache/34D/E30/shard%2F139 +0 -0
- data/spec/dummy/tmp/cache/34E/E50/shard%2F149 +0 -0
- data/spec/dummy/tmp/cache/353/EF0/shard%2F199 +1 -0
- data/spec/dummy/tmp/cache/3A4/E90/shard%2F10003 +1 -0
- data/spec/dummy/tmp/cache/3A5/ED0/shard%2F10031 +1 -0
- data/spec/dummy/tmp/cache/3A9/EF0/shard%2F10017 +1 -0
- data/spec/lib/active_record/association_spec.rb +305 -0
- data/spec/lib/active_record/attribute_methods_spec.rb +108 -0
- data/spec/lib/active_record/base_spec.rb +66 -0
- data/spec/lib/active_record/calculations_spec.rb +119 -0
- data/spec/lib/active_record/connection_handler_spec.rb +45 -0
- data/spec/lib/active_record/connection_pool_spec.rb +23 -0
- data/spec/lib/active_record/finder_methods_spec.rb +29 -0
- data/spec/lib/active_record/query_cache_spec.rb +20 -0
- data/spec/lib/active_record/query_methods_spec.rb +130 -0
- data/spec/lib/active_record/relation_spec.rb +38 -0
- data/spec/lib/cache_extensions_spec.rb +27 -0
- data/spec/lib/connection_pool_proxy_spec.rb +13 -0
- data/spec/lib/database_server_spec.rb +154 -0
- data/spec/lib/shackles_spec.rb +147 -0
- data/spec/models/shard_spec.rb +382 -0
- data/spec/spec_helper.rb +32 -0
- metadata +344 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe AttributeMethods do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
describe "ids" do
|
9
|
+
it "should return id relative to the current shard" do
|
10
|
+
user = User.create!
|
11
|
+
user.id.should < Shard::IDS_PER_SHARD
|
12
|
+
user.local_id.should < Shard::IDS_PER_SHARD
|
13
|
+
user.global_id.should > Shard::IDS_PER_SHARD
|
14
|
+
|
15
|
+
@shard1.activate do
|
16
|
+
user.id.should > Shard::IDS_PER_SHARD
|
17
|
+
user.local_id.should < Shard::IDS_PER_SHARD
|
18
|
+
user.global_id.should > Shard::IDS_PER_SHARD
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return foreign keys relative to the current shard" do
|
23
|
+
appendage = Appendage.create!
|
24
|
+
|
25
|
+
# bypass the setter; we're going to test it in just a minute
|
26
|
+
|
27
|
+
# local id, should stay local
|
28
|
+
appendage.original_user_id = 6
|
29
|
+
appendage.user_id.should == 6
|
30
|
+
|
31
|
+
# (incorrect) self referencing global id; should come out as local
|
32
|
+
appendage.original_user_id = Shard.current.global_id_for(6)
|
33
|
+
appendage.user_id.should == 6
|
34
|
+
|
35
|
+
# global id referencing another shard; should come out unscathed
|
36
|
+
appendage.original_user_id = @shard1.global_id_for(6)
|
37
|
+
appendage.user_id.should == @shard1.global_id_for(6)
|
38
|
+
|
39
|
+
@shard1.activate do
|
40
|
+
# local id in another shard, should be global in this shard
|
41
|
+
appendage.original_user_id = 6
|
42
|
+
appendage.user_id.should == Shard.default.global_id_for(6)
|
43
|
+
|
44
|
+
# (incorrect) self referencing global id; should come out as global in this shard
|
45
|
+
appendage.original_user_id = Shard.default.global_id_for(6)
|
46
|
+
appendage.user_id.should == Shard.default.global_id_for(6)
|
47
|
+
|
48
|
+
# global id referencing this shard; should come out as a local id in this shard
|
49
|
+
appendage.original_user_id = @shard1.global_id_for(6)
|
50
|
+
appendage.user_id.should == 6
|
51
|
+
|
52
|
+
# global id from an unrelated shard; should stay global
|
53
|
+
appendage.original_user_id = @shard2.global_id_for(6)
|
54
|
+
appendage.user_id.should == @shard2.global_id_for(6)
|
55
|
+
end
|
56
|
+
|
57
|
+
# now that we trust the getters, try the setters
|
58
|
+
|
59
|
+
# local stays local
|
60
|
+
appendage.user_id = 6
|
61
|
+
appendage.original_user_id.should == 6
|
62
|
+
appendage.user_id = '6'
|
63
|
+
appendage.original_user_id.should == 6
|
64
|
+
|
65
|
+
# (incorrect) global id to this shard, should become local
|
66
|
+
appendage.user_id = Shard.current.global_id_for(6)
|
67
|
+
appendage.original_user_id.should == 6
|
68
|
+
appendage.user_id = Shard.current.global_id_for(6).to_s
|
69
|
+
appendage.original_user_id.should == 6
|
70
|
+
|
71
|
+
# global id from another shard, should stay global
|
72
|
+
appendage.user_id = @shard1.global_id_for(6)
|
73
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
74
|
+
appendage.local_user_id.should == 6
|
75
|
+
appendage.user_id = @shard1.global_id_for(6).to_s
|
76
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
77
|
+
appendage.local_user_id.should == 6
|
78
|
+
|
79
|
+
@shard1.activate do
|
80
|
+
# local to this shard becomes global
|
81
|
+
appendage.user_id = 6
|
82
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
83
|
+
appendage.user_id = '6'
|
84
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
85
|
+
|
86
|
+
# global id from original shard, should become local
|
87
|
+
appendage.user_id = Shard.default.global_id_for(6)
|
88
|
+
appendage.original_user_id.should == 6
|
89
|
+
appendage.user_id = Shard.default.global_id_for(6).to_s
|
90
|
+
appendage.original_user_id.should == 6
|
91
|
+
|
92
|
+
# global id from this shard, should stay global
|
93
|
+
appendage.user_id = Shard.current.global_id_for(6)
|
94
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
95
|
+
appendage.user_id = Shard.current.global_id_for(6).to_s
|
96
|
+
appendage.original_user_id.should == @shard1.global_id_for(6)
|
97
|
+
|
98
|
+
# global id from unrelated shard, should stay global
|
99
|
+
appendage.user_id = @shard2.global_id_for(6)
|
100
|
+
appendage.original_user_id.should == @shard2.global_id_for(6)
|
101
|
+
appendage.user_id = @shard2.global_id_for(6).to_s
|
102
|
+
appendage.original_user_id.should == @shard2.global_id_for(6)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe Base do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
describe "to_param" do
|
9
|
+
it "should return nil if not persisted" do
|
10
|
+
user = User.new
|
11
|
+
user.to_param.should be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return local id if in the current shard" do
|
15
|
+
user = User.create!
|
16
|
+
user.to_param.should == user.local_id
|
17
|
+
@shard1.activate do
|
18
|
+
user2 = User.create!
|
19
|
+
user2.to_param.should == user2.local_id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return a short form global id if not in the current shard" do
|
24
|
+
user = nil
|
25
|
+
@shard1.activate do
|
26
|
+
user = User.create!
|
27
|
+
end
|
28
|
+
@shard2.activate do
|
29
|
+
user.to_param.should == "#{@shard1.id}~#{user.local_id}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should use to_param in url helpers" do
|
34
|
+
helpers = Rails.application.routes.url_helpers
|
35
|
+
user = nil
|
36
|
+
appendage = nil
|
37
|
+
|
38
|
+
@shard1.activate do
|
39
|
+
user = User.create!
|
40
|
+
appendage = Appendage.create!
|
41
|
+
|
42
|
+
helpers.user_path(user).should == "/users/#{user.local_id}"
|
43
|
+
helpers.user_appendages_path(user).should == "/users/#{user.local_id}/appendages"
|
44
|
+
helpers.user_appendage_path(user, appendage).should == "/users/#{user.local_id}/appendages/#{appendage.local_id}"
|
45
|
+
helpers.user_test1_path(user).should == "/users/#{user.local_id}"
|
46
|
+
helpers.user_test2_path(user).should == "/users/#{user.local_id}/test2"
|
47
|
+
end
|
48
|
+
|
49
|
+
@shard2.activate do
|
50
|
+
user_short_id = "#{@shard1.id}~#{user.local_id}"
|
51
|
+
appendage_short_id = "#{@shard1.id}~#{appendage.local_id}"
|
52
|
+
|
53
|
+
helpers.user_path(user).should == "/users/#{user_short_id}"
|
54
|
+
helpers.user_appendages_path(user).should == "/users/#{user_short_id}/appendages"
|
55
|
+
helpers.user_appendage_path(user, appendage).should == "/users/#{user_short_id}/appendages/#{appendage_short_id}"
|
56
|
+
helpers.user_test1_path(user).should == "/users/#{user_short_id}"
|
57
|
+
helpers.user_test2_path(user).should == "/users/#{user_short_id}/test2"
|
58
|
+
|
59
|
+
appendage2 = Appendage.create!
|
60
|
+
helpers.user_appendage_path(user, appendage2).should == "/users/#{user_short_id}/appendages/#{appendage2.local_id}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe Calculations do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
describe "#pluck" do
|
9
|
+
before do
|
10
|
+
@shard1.activate do
|
11
|
+
@user1 = User.create!(:name => "user1")
|
12
|
+
@appendage1 = @user1.appendages.create!
|
13
|
+
end
|
14
|
+
@shard2.activate do
|
15
|
+
@user2 = User.create!(:name => "user2")
|
16
|
+
@appendage2 = @user2.appendages.create!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return non-id columns" do
|
21
|
+
User.where(:id => [@user1.id, @user2.id]).pluck(:name).sort.should == ["user1", "user2"]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return primary ids relative to current shard" do
|
25
|
+
Appendage.where(:id => @appendage1).pluck(:id).should == [@appendage1.global_id]
|
26
|
+
Appendage.where(:id => @appendage2).pluck(:id).should == [@appendage2.global_id]
|
27
|
+
@shard1.activate do
|
28
|
+
Appendage.where(:id => @appendage1).pluck(:id).should == [@appendage1.local_id]
|
29
|
+
Appendage.where(:id => @appendage2).pluck(:id).should == [@appendage2.global_id]
|
30
|
+
end
|
31
|
+
@shard2.activate do
|
32
|
+
Appendage.where(:id => @appendage1).pluck(:id).should == [@appendage1.global_id]
|
33
|
+
Appendage.where(:id => @appendage2).pluck(:id).should == [@appendage2.local_id]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return foreign ids relative to current shard" do
|
38
|
+
Appendage.where(:id => @appendage1).pluck(:user_id).should == [@user1.global_id]
|
39
|
+
Appendage.where(:id => @appendage2).pluck(:user_id).should == [@user2.global_id]
|
40
|
+
@shard1.activate do
|
41
|
+
Appendage.where(:id => @appendage1).pluck(:user_id).should == [@user1.local_id]
|
42
|
+
Appendage.where(:id => @appendage2).pluck(:user_id).should == [@user2.global_id]
|
43
|
+
end
|
44
|
+
@shard2.activate do
|
45
|
+
Appendage.where(:id => @appendage1).pluck(:user_id).should == [@user1.global_id]
|
46
|
+
Appendage.where(:id => @appendage2).pluck(:user_id).should == [@user2.local_id]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#execute_simple_calculation" do
|
52
|
+
before do
|
53
|
+
@appendages = []
|
54
|
+
@shard1.activate do
|
55
|
+
@user1 = User.create!(:name => "user1")
|
56
|
+
@appendages << @user1.appendages.create!(:value => 1)
|
57
|
+
@appendages << @user1.appendages.create!(:value => 2)
|
58
|
+
end
|
59
|
+
@shard2.activate do
|
60
|
+
@user2 = User.create!(:name => "user2")
|
61
|
+
@appendages << @user2.appendages.create!(:value => 3)
|
62
|
+
@appendages << @user2.appendages.create!(:value => 4)
|
63
|
+
@appendages << @user2.appendages.create!(:value => 5)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should calculate average across shards" do
|
68
|
+
@user1.appendages.average(:value).should == 1.5
|
69
|
+
@shard1.activate {Appendage.average(:value)}.should == 1.5
|
70
|
+
|
71
|
+
@user2.appendages.average(:value).should == 4
|
72
|
+
@shard2.activate {Appendage.average(:value)}.should == 4
|
73
|
+
|
74
|
+
Appendage.where(:id => @appendages).average(:value).should == 3
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should count across shards" do
|
78
|
+
@user1.appendages.count.should == 2
|
79
|
+
@shard1.activate {Appendage.count}.should == 2
|
80
|
+
|
81
|
+
@user2.appendages.count.should == 3
|
82
|
+
@shard2.activate {Appendage.count}.should == 3
|
83
|
+
|
84
|
+
Appendage.where(:id => @appendages).count.should == 5
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should calculate minimum across shards" do
|
88
|
+
@user1.appendages.minimum(:value).should == 1
|
89
|
+
@shard1.activate {Appendage.minimum(:value)}.should == 1
|
90
|
+
|
91
|
+
@user2.appendages.minimum(:value).should == 3
|
92
|
+
@shard2.activate {Appendage.minimum(:value)}.should == 3
|
93
|
+
|
94
|
+
Appendage.where(:id => @appendages).minimum(:value).should == 1
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should calculate maximum across shards" do
|
98
|
+
@user1.appendages.maximum(:value).should == 2
|
99
|
+
@shard1.activate {Appendage.maximum(:value)}.should == 2
|
100
|
+
|
101
|
+
@user2.appendages.maximum(:value).should == 5
|
102
|
+
@shard2.activate {Appendage.maximum(:value)}.should == 5
|
103
|
+
|
104
|
+
Appendage.where(:id => @appendages).maximum(:value).should == 5
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should calculate sum across shards" do
|
108
|
+
@user1.appendages.sum(:value).should == 3
|
109
|
+
@shard1.activate {Appendage.sum(:value)}.should == 3
|
110
|
+
|
111
|
+
@user2.appendages.sum(:value).should == 12
|
112
|
+
@shard2.activate {Appendage.sum(:value)}.should == 12
|
113
|
+
|
114
|
+
Appendage.where(:id => @appendages).sum(:value).should == 15
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe ConnectionHandler do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
it "should use different proxies for different categories" do
|
9
|
+
Shard.connection_pool.should_not == User.connection_pool
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should share underlying pools for different categories on the same shard" do
|
13
|
+
Shard.connection_pool.current_pool.should == User.connection_pool.current_pool
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should insert sharding for connections established after initialization" do
|
17
|
+
User.connection_pool.should == ::ActiveRecord::Base.connection_pool
|
18
|
+
begin
|
19
|
+
config = { :adapter => 'sqlite3', :database => ':memory:', :something_unique_in_the_spec => true }
|
20
|
+
User.establish_connection(config)
|
21
|
+
User.connection_pool.should_not == ::ActiveRecord::Base.connection_pool
|
22
|
+
User.connection_pool.spec.config.should == config
|
23
|
+
User.connection_pool.should be_is_a(ConnectionPoolProxy)
|
24
|
+
@shard2.activate do
|
25
|
+
User.connection_pool.spec.config.should == ::ActiveRecord::Base.connection_pool.spec.config
|
26
|
+
User.connection_pool.spec.config.should_not == config
|
27
|
+
end
|
28
|
+
ensure
|
29
|
+
User.remove_connection
|
30
|
+
User.connection_pool.should == ::ActiveRecord::Base.connection_pool
|
31
|
+
User.connection_pool.should be_is_a(ConnectionPoolProxy)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should set up separate pools for different categories" do
|
36
|
+
User.connection_pool.should_not == MirrorUser.connection_pool
|
37
|
+
mu = MirrorUser.create!
|
38
|
+
MirrorUser.find(mu.local_id).should == mu
|
39
|
+
# didn't activate the :mirror_universe category
|
40
|
+
@shard1.activate { MirrorUser.find(mu.local_id).should == mu }
|
41
|
+
@shard1.activate(:mirror_universe) { MirrorUser.find_by_id(mu.local_id).should == nil }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe ConnectionPool do
|
6
|
+
it "should be able to access another shard on a db server after the 'primary' shard is gone" do
|
7
|
+
pending 'A "real" database"' unless Shard.default.database_server.shareable?
|
8
|
+
# separate connections
|
9
|
+
server = DatabaseServer.create(:config => Shard.default.database_server.config.dup)
|
10
|
+
s1 = server.shards.create!(:name => 'non_existent_shard') # don't actually create any schema
|
11
|
+
s2 = server.shards.create! # inherit's the default shard's config, which is functional
|
12
|
+
s1.activate do
|
13
|
+
lambda { User.count }.should raise_exception
|
14
|
+
end
|
15
|
+
# the config for s1 should not be the permanent default for all new
|
16
|
+
# connections now
|
17
|
+
s2.activate do
|
18
|
+
lambda { User.count }.should_not raise_exception
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe FinderMethods do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@user = @shard1.activate { User.create! }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#find_one" do
|
13
|
+
it "should find with a global id" do
|
14
|
+
User.find(@user.global_id).should == @user
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#find_by_attributes" do
|
19
|
+
it "should find with a global id" do
|
20
|
+
User.find_by_id(@user.global_id).should == @user
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should find with an array of global ids" do
|
24
|
+
User.find_by_id([@user.global_id]).should == @user
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe QueryCache do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
it "should isolate queries to multiple shards on the same server" do
|
9
|
+
@shard1.activate do
|
10
|
+
User.create!
|
11
|
+
User.create!
|
12
|
+
end
|
13
|
+
@shard3.activate do
|
14
|
+
User.create!
|
15
|
+
end
|
16
|
+
@shard1.activate { User.all }.should_not == @shard3.activate { User.all }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Switchman
|
4
|
+
module ActiveRecord
|
5
|
+
describe QueryMethods do
|
6
|
+
include RSpecHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@user1 = User.create!
|
10
|
+
@appendage1 = @user1.appendages.create!
|
11
|
+
@user2 = @shard1.activate { User.create! }
|
12
|
+
@appendage2 = @user2.appendages.create!
|
13
|
+
@user3 = @shard2.activate { User.create! }
|
14
|
+
@appendage3 = @user3.appendages.create!
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#primary_shard" do
|
18
|
+
it "should be the shard if it's a shard" do
|
19
|
+
User.shard(Shard.default).primary_shard.should == Shard.default
|
20
|
+
User.shard(@shard1).primary_shard.should == @shard1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be the first shard of an array of shards" do
|
24
|
+
User.shard([Shard.default, @shard1]).primary_shard.should == Shard.default
|
25
|
+
User.shard([@shard1, Shard.default]).primary_shard.should == @shard1
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be the object's shard if it's a model" do
|
29
|
+
User.shard(@user1).primary_shard.should == Shard.default
|
30
|
+
User.shard(@user2).primary_shard.should == @shard1
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be the default shard if it's a scope of Shard" do
|
34
|
+
User.shard(Shard.scoped).primary_shard.should == Shard.default
|
35
|
+
@shard1.activate do
|
36
|
+
User.shard(Shard.scoped).primary_shard.should == Shard.default
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should default to the current shard" do
|
42
|
+
relation = User.scoped
|
43
|
+
relation.shard_value.should == Shard.default
|
44
|
+
relation.shard_source_value.should == :implicit
|
45
|
+
|
46
|
+
@shard1.activate do
|
47
|
+
relation.shard_value.should == Shard.default
|
48
|
+
|
49
|
+
relation = User.scoped
|
50
|
+
relation.shard_value.should == @shard1
|
51
|
+
relation.shard_source_value.should == :implicit
|
52
|
+
end
|
53
|
+
relation.shard_value.should == @shard1
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "with primary key conditions" do
|
57
|
+
it "should be changeable, and change conditions when it is changed" do
|
58
|
+
relation = User.where(:id => @user1).shard(@shard1)
|
59
|
+
relation.shard_value.should == @shard1
|
60
|
+
relation.shard_source_value.should == :explicit
|
61
|
+
relation.where_values.first.right.should == @user1.global_id
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should infer the shard from a single argument" do
|
65
|
+
relation = User.where(:id => @user2)
|
66
|
+
# execute on @shard1, with id local to that shard
|
67
|
+
relation.shard_value.should == @shard1
|
68
|
+
relation.where_values.first.right.should == @user2.local_id
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should infer the shard from multiple arguments" do
|
72
|
+
relation = User.where(:id => [@user2, @user2])
|
73
|
+
# execute on @shard1, with id local to that shard
|
74
|
+
relation.shard_value.should == @shard1
|
75
|
+
relation.where_values.first.right.should == [@user2.local_id, @user2.local_id]
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should infer the correct shard from an array of 1" do
|
79
|
+
relation = User.where(:id => [@user2])
|
80
|
+
# execute on @shard1, with id local to that shard
|
81
|
+
relation.shard_value.should == @shard1
|
82
|
+
relation.where_values.first.right.should == [@user2.local_id]
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should do nothing when it's an array of 0" do
|
86
|
+
relation = User.where(:id => [])
|
87
|
+
# execute on @shard1, with id local to that shard
|
88
|
+
relation.shard_value.should == Shard.default
|
89
|
+
relation.where_values.first.right.should == []
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should order the shards preferring the shard it already had as primary" do
|
93
|
+
relation = User.where(:id => [@user1, @user2])
|
94
|
+
relation.shard_value.should == [Shard.default, @shard1]
|
95
|
+
relation.where_values.first.right.should == [@user1.local_id, @user2.global_id]
|
96
|
+
|
97
|
+
@shard1.activate do
|
98
|
+
relation = User.where(:id => [@user1, @user2])
|
99
|
+
relation.shard_value.should == [@shard1, Shard.default]
|
100
|
+
relation.where_values.first.right.should == [@user1.global_id, @user2.local_id]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "with foreign key conditions" do
|
106
|
+
it "should be changeable, and change conditions when it is changed" do
|
107
|
+
relation = Appendage.where(:user_id => @user1)
|
108
|
+
relation.shard_value.should == Shard.default
|
109
|
+
relation.shard_source_value.should == :implicit
|
110
|
+
relation.where_values.first.right.should == @user1.local_id
|
111
|
+
|
112
|
+
relation = relation.shard(@shard1)
|
113
|
+
relation.shard_value.should == @shard1
|
114
|
+
relation.shard_source_value.should == :explicit
|
115
|
+
relation.where_values.first.right.should == @user1.global_id
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should translate ids based on current shard" do
|
119
|
+
relation = Appendage.where(:user_id => [@user1, @user2])
|
120
|
+
relation.where_values.first.right.should == [@user1.local_id, @user2.global_id]
|
121
|
+
|
122
|
+
@shard1.activate do
|
123
|
+
relation = Appendage.where(:user_id => [@user1, @user2])
|
124
|
+
relation.where_values.first.right.should == [@user1.global_id, @user2.local_id]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|