ar-octopus 0.0.4 → 0.0.5
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.
- data/Rakefile +2 -1
- data/ar-octopus.gemspec +6 -1
- data/lib/octopus/model.rb +2 -5
- data/lib/octopus/proxy.rb +15 -16
- data/spec/octopus/model_spec.rb +9 -2
- data/spec/octopus/proxy_spec.rb +0 -51
- data/spec/octopus/replication_specs.rb +46 -0
- metadata +19 -3
data/Rakefile
CHANGED
@@ -28,7 +28,8 @@ begin
|
|
28
28
|
gem.homepage = "http://github.com/tchandy/octopus"
|
29
29
|
gem.authors = ["Thiago Pradi", "Mike Perham", "Amit Agarwal"]
|
30
30
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
31
|
-
gem.
|
31
|
+
gem.add_dependency('activerecord')
|
32
|
+
gem.version = "0.0.5"
|
32
33
|
end
|
33
34
|
Jeweler::GemcutterTasks.new
|
34
35
|
rescue LoadError
|
data/ar-octopus.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ar-octopus}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Thiago Pradi", "Mike Perham", "Amit Agarwal"]
|
@@ -54,6 +54,7 @@ Gem::Specification.new do |s|
|
|
54
54
|
"spec/octopus/model_spec.rb",
|
55
55
|
"spec/octopus/octopus_spec.rb",
|
56
56
|
"spec/octopus/proxy_spec.rb",
|
57
|
+
"spec/octopus/replication_specs.rb",
|
57
58
|
"spec/octopus_helper.rb",
|
58
59
|
"spec/spec.opts",
|
59
60
|
"spec/spec_helper.rb"
|
@@ -83,6 +84,7 @@ Gem::Specification.new do |s|
|
|
83
84
|
"spec/octopus/model_spec.rb",
|
84
85
|
"spec/octopus/octopus_spec.rb",
|
85
86
|
"spec/octopus/proxy_spec.rb",
|
87
|
+
"spec/octopus/replication_specs.rb",
|
86
88
|
"spec/octopus_helper.rb",
|
87
89
|
"spec/spec_helper.rb"
|
88
90
|
]
|
@@ -93,11 +95,14 @@ Gem::Specification.new do |s|
|
|
93
95
|
|
94
96
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
95
97
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
98
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
96
99
|
else
|
97
100
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
101
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
98
102
|
end
|
99
103
|
else
|
100
104
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
105
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
data/lib/octopus/model.rb
CHANGED
@@ -53,10 +53,7 @@ module Octopus::Model
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def connection
|
56
|
-
|
57
|
-
self.connection_proxy().set_replicated_model(self)
|
58
|
-
end
|
59
|
-
|
56
|
+
self.connection_proxy().current_model = self
|
60
57
|
self.connection_proxy()
|
61
58
|
end
|
62
59
|
end
|
@@ -98,7 +95,7 @@ module Octopus::Model
|
|
98
95
|
include InstanceMethods
|
99
96
|
|
100
97
|
def replicated_model()
|
101
|
-
|
98
|
+
write_inheritable_attribute(:replicated, true)
|
102
99
|
end
|
103
100
|
|
104
101
|
def has_many(association_id, options = {}, &extension)
|
data/lib/octopus/proxy.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
require "set"
|
2
2
|
|
3
3
|
class Octopus::Proxy
|
4
|
-
attr_accessor :shards, :block, :groups, :current_group, :replicated, :slaves_list, :
|
4
|
+
attr_accessor :shards, :block, :current_model, :current_shard, :groups, :current_group, :replicated, :slaves_list, :using_enabled, :last_current_shard
|
5
5
|
|
6
6
|
delegate :increment_open_transactions, :decrement_open_transactions, :to => :select_connection
|
7
7
|
|
8
8
|
def initialize(config)
|
9
9
|
@shards = {}
|
10
10
|
@groups = {}
|
11
|
-
@replicated_models = Set.new
|
12
11
|
@replicated = config[Octopus.env()]["replicated"]
|
13
12
|
@shards[:master] = ActiveRecord::Base.connection_pool()
|
14
|
-
|
13
|
+
@current_shard = :master
|
15
14
|
|
16
15
|
initialize_shards(config)
|
17
16
|
|
@@ -43,10 +42,7 @@ class Octopus::Proxy
|
|
43
42
|
@slaves_list.delete(:master)
|
44
43
|
@slaves_list = @slaves_list.map {|sym| sym.to_s}.sort
|
45
44
|
end
|
46
|
-
|
47
|
-
def current_shard
|
48
|
-
Thread.current[:current_shard]
|
49
|
-
end
|
45
|
+
|
50
46
|
|
51
47
|
def current_shard=(shard_symbol)
|
52
48
|
if shard_symbol.is_a?(Array)
|
@@ -55,7 +51,7 @@ class Octopus::Proxy
|
|
55
51
|
raise "Nonexistent Shard Name: #{shard_symbol}" if @shards[shard_symbol].nil?
|
56
52
|
end
|
57
53
|
|
58
|
-
|
54
|
+
@current_shard = shard_symbol
|
59
55
|
end
|
60
56
|
|
61
57
|
def current_group=(group_symbol)
|
@@ -68,6 +64,14 @@ class Octopus::Proxy
|
|
68
64
|
@current_group = group_symbol
|
69
65
|
end
|
70
66
|
|
67
|
+
def current_model=(model)
|
68
|
+
if model.is_a?(ActiveRecord::Base)
|
69
|
+
@current_model = model.class
|
70
|
+
else
|
71
|
+
@current_model = model
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
71
75
|
def select_connection()
|
72
76
|
@shards[shard_name].connection()
|
73
77
|
end
|
@@ -79,11 +83,7 @@ class Octopus::Proxy
|
|
79
83
|
current_shard
|
80
84
|
end
|
81
85
|
end
|
82
|
-
|
83
|
-
def set_replicated_model(model)
|
84
|
-
replicated_models << model.to_s
|
85
|
-
end
|
86
|
-
|
86
|
+
|
87
87
|
def add_transaction_record(record)
|
88
88
|
if !select_connection().instance_variable_get(:@_current_transaction_records).nil?
|
89
89
|
select_connection().add_transaction_record(record)
|
@@ -195,10 +195,9 @@ class Octopus::Proxy
|
|
195
195
|
end
|
196
196
|
|
197
197
|
def send_queries_to_selected_slave(method, *args, &block)
|
198
|
-
#TODO: UGLY code, needs refactor
|
199
198
|
old_shard = self.current_shard
|
200
|
-
|
201
|
-
if
|
199
|
+
|
200
|
+
if current_model.read_inheritable_attribute(:replicated)
|
202
201
|
if !using_enabled
|
203
202
|
self.current_shard = slaves_list.shift.to_sym
|
204
203
|
slaves_list << self.current_shard
|
data/spec/octopus/model_spec.rb
CHANGED
@@ -11,6 +11,13 @@ describe Octopus::Model do
|
|
11
11
|
User.using(:canada).count.should == 1
|
12
12
|
User.count.should == 0
|
13
13
|
end
|
14
|
+
|
15
|
+
it "should select the correct shard" do
|
16
|
+
pending()
|
17
|
+
# User.using(:canada)
|
18
|
+
# User.create!(:name => 'oi')
|
19
|
+
# User.using(:master).count.should == 1
|
20
|
+
end
|
14
21
|
|
15
22
|
it "should allow scoping dynamically" do
|
16
23
|
User.using(:canada).using(:master).using(:canada).create!(:name => 'oi')
|
@@ -144,8 +151,8 @@ describe Octopus::Model do
|
|
144
151
|
|
145
152
|
it "should mark the Cat model as replicated" do
|
146
153
|
using_enviroment :production_replicated do
|
147
|
-
|
148
|
-
|
154
|
+
User.read_inheritable_attribute(:replicated).should be_false
|
155
|
+
Cat.read_inheritable_attribute(:replicated).should be_true
|
149
156
|
end
|
150
157
|
end
|
151
158
|
end
|
data/spec/octopus/proxy_spec.rb
CHANGED
@@ -57,55 +57,4 @@ describe Octopus::Proxy do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
61
|
-
describe "when the database is replicated" do
|
62
|
-
before(:each) do
|
63
|
-
Octopus.stub!(:env).and_return("production_replicated")
|
64
|
-
@proxy = Octopus::Proxy.new(Octopus.config())
|
65
|
-
clean_connection_proxy()
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should have the replicated attribute as true" do
|
69
|
-
@proxy.replicated.should be_true
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should initialize the list of shards" do
|
73
|
-
@proxy.slaves_list.should == ["slave1", "slave2", "slave3", "slave4"]
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should send all writes queries to master" do
|
77
|
-
u = User.create!(:name => "Replicated")
|
78
|
-
|
79
|
-
[:slave4, :slave1, :slave2, :slave3].each do |sym|
|
80
|
-
User.using(sym).count.should == 0
|
81
|
-
end
|
82
|
-
|
83
|
-
User.using(:master).count.should == 1
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should send read queries to slaves, using a round robin algorithm" do
|
87
|
-
u = Cat.create!(:name => "master")
|
88
|
-
c = Client.create!(:name => "client_master")
|
89
|
-
|
90
|
-
[:slave4, :slave1, :slave2, :slave3].each do |sym|
|
91
|
-
Cat.using(sym).create!(:name => "Replicated_#{sym}")
|
92
|
-
end
|
93
|
-
|
94
|
-
Client.find(:first).should_not be_nil
|
95
|
-
Cat.find(:first).name.should == "Replicated_slave1"
|
96
|
-
Client.find(:first).should_not be_nil
|
97
|
-
Cat.find(:first).name.should == "Replicated_slave2"
|
98
|
-
Client.find(:first).should_not be_nil
|
99
|
-
Cat.find(:first).name.should == "Replicated_slave3"
|
100
|
-
Client.find(:first).should_not be_nil
|
101
|
-
Cat.find(:first).name.should == "Replicated_slave4"
|
102
|
-
Client.find(:first).should_not be_nil
|
103
|
-
Cat.find(:first).name.should == "Replicated_slave1"
|
104
|
-
Client.find(:first).should_not be_nil
|
105
|
-
|
106
|
-
[:slave4, :slave1, :slave2, :slave3].each do |sym|
|
107
|
-
Cat.using(sym).find_by_name("master").should be_false
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
60
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
describe "when the database is replicated" do
|
2
|
+
before(:each) do
|
3
|
+
Octopus.stub!(:env).and_return("production_replicated")
|
4
|
+
@proxy = Octopus::Proxy.new(Octopus.config())
|
5
|
+
clean_connection_proxy()
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have the replicated attribute as true" do
|
9
|
+
@proxy.replicated.should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize the list of shards" do
|
13
|
+
@proxy.slaves_list.should == ["slave1", "slave2", "slave3", "slave4"]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should send all writes/reads queries to master when you have a replicated model" do
|
17
|
+
u = User.create!(:name => "Replicated")
|
18
|
+
User.count.should == 1
|
19
|
+
User.find(u.id).should == u
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should send read queries to slaves, when you have a replicated model, using a round robin algorithm" do
|
23
|
+
u = Cat.create!(:name => "master")
|
24
|
+
c = Client.create!(:name => "client_master")
|
25
|
+
|
26
|
+
[:slave4, :slave1, :slave2, :slave3].each do |sym|
|
27
|
+
Cat.using(sym).create!(:name => "Replicated_#{sym}")
|
28
|
+
end
|
29
|
+
|
30
|
+
Client.find(:first).should_not be_nil
|
31
|
+
Cat.find(:first).name.should == "Replicated_slave1"
|
32
|
+
Client.find(:first).should_not be_nil
|
33
|
+
Cat.find(:first).name.should == "Replicated_slave2"
|
34
|
+
Client.find(:first).should_not be_nil
|
35
|
+
Cat.find(:first).name.should == "Replicated_slave3"
|
36
|
+
Client.find(:first).should_not be_nil
|
37
|
+
Cat.find(:first).name.should == "Replicated_slave4"
|
38
|
+
Client.find(:first).should_not be_nil
|
39
|
+
Cat.find(:first).name.should == "Replicated_slave1"
|
40
|
+
Client.find(:first).should_not be_nil
|
41
|
+
|
42
|
+
[:slave4, :slave1, :slave2, :slave3].each do |sym|
|
43
|
+
Cat.using(sym).find_by_name("master").should be_false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-octopus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Thiago Pradi
|
@@ -36,6 +36,20 @@ dependencies:
|
|
36
36
|
version: 1.2.9
|
37
37
|
type: :development
|
38
38
|
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: activerecord
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 3
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
39
53
|
description: This gem allows you to use sharded databases with ActiveRecord. this also provides a interface for replication and for running migrations with multiples shards.
|
40
54
|
email: tchandy@gmail.com
|
41
55
|
executables: []
|
@@ -83,6 +97,7 @@ files:
|
|
83
97
|
- spec/octopus/model_spec.rb
|
84
98
|
- spec/octopus/octopus_spec.rb
|
85
99
|
- spec/octopus/proxy_spec.rb
|
100
|
+
- spec/octopus/replication_specs.rb
|
86
101
|
- spec/octopus_helper.rb
|
87
102
|
- spec/spec.opts
|
88
103
|
- spec/spec_helper.rb
|
@@ -140,5 +155,6 @@ test_files:
|
|
140
155
|
- spec/octopus/model_spec.rb
|
141
156
|
- spec/octopus/octopus_spec.rb
|
142
157
|
- spec/octopus/proxy_spec.rb
|
158
|
+
- spec/octopus/replication_specs.rb
|
143
159
|
- spec/octopus_helper.rb
|
144
160
|
- spec/spec_helper.rb
|