ar-octopus 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -29,7 +29,7 @@ begin
29
29
  gem.authors = ["Thiago Pradi", "Mike Perham", "Amit Agarwal"]
30
30
  gem.add_development_dependency "rspec", ">= 1.2.9"
31
31
  gem.add_dependency('activerecord')
32
- gem.version = "0.0.5"
32
+ gem.version = "0.0.6"
33
33
  end
34
34
  Jeweler::GemcutterTasks.new
35
35
  rescue LoadError
@@ -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.5"
8
+ s.version = "0.0.6"
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"]
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "lib/octopus/has_and_belongs_to_many_association.rb",
33
33
  "lib/octopus/migration.rb",
34
34
  "lib/octopus/model.rb",
35
+ "lib/octopus/persistence.rb",
35
36
  "lib/octopus/proxy.rb",
36
37
  "rails/init.rb",
37
38
  "spec/config/shards.yml",
@@ -19,6 +19,7 @@ end
19
19
  require "octopus/proxy"
20
20
  require "octopus/migration"
21
21
  require "octopus/model"
22
+ require "octopus/persistence"
22
23
  require "octopus/controller"
23
24
  require "octopus/association"
24
25
  require "octopus/association_collection"
@@ -1,4 +1,28 @@
1
1
  module Octopus::Association
2
+ def has_many(association_id, options = {}, &extension)
3
+ default_octopus_opts(options)
4
+ super(association_id, options, &extension)
5
+ end
6
+
7
+ def has_and_belongs_to_many(association_id, options = {}, &extension)
8
+ default_octopus_opts(options)
9
+ super(association_id, options, &extension)
10
+ end
11
+
12
+ def default_octopus_opts(options)
13
+ if options[:before_add].is_a?(Array)
14
+ options[:before_add] << :set_connection
15
+ else
16
+ options[:before_add] = :set_connection
17
+ end
18
+
19
+ if options[:before_remove].is_a?(Array)
20
+ options[:before_remove] << :set_connection
21
+ else
22
+ options[:before_remove] = :set_connection
23
+ end
24
+ end
25
+
2
26
  def collection_reader_method(reflection, association_proxy_class)
3
27
  define_method(reflection.name) do |*params|
4
28
  force_reload = params.first unless params.empty?
@@ -60,13 +84,13 @@ module Octopus::Association
60
84
 
61
85
  def association_accessor_methods(reflection, association_proxy_class)
62
86
  define_method(reflection.name) do |*params|
63
- force_reload = true
64
87
  reload_connection()
88
+ force_reload = params.first unless params.empty?
65
89
  association = association_instance_get(reflection.name)
66
90
 
67
91
  if association.nil? || force_reload
68
92
  association = association_proxy_class.new(self, reflection)
69
- retval = have_a_valid_shard? ? reflection.klass.uncached { self.class.connection_proxy.run_query_on_shard(self.current_shard) { association.reload } } : association.reload
93
+ retval = have_a_valid_shard? ? reflection.klass.uncached { self.class.connection_proxy.run_queries_on_shard(self.current_shard) { association.reload } } : association.reload
70
94
  if retval.nil? and association_proxy_class == ActiveRecord::Associations::BelongsToAssociation
71
95
  association_instance_set(reflection.name, nil)
72
96
  return nil
@@ -1,6 +1,6 @@
1
1
  module Octopus::Controller
2
2
  def using(shard, &block)
3
- ActiveRecord::Base.connection_proxy.run_query_on_shard(shard, &block)
3
+ ActiveRecord::Base.connection.run_queries_on_shard(shard, &block)
4
4
  end
5
5
  end
6
6
 
@@ -1,34 +1,30 @@
1
1
  module Octopus::Model
2
2
  def self.extended(base)
3
3
  base.send(:include, InstanceMethods)
4
+ base.extend(ClassMethods)
4
5
  base.hijack_connection()
5
6
  end
6
7
 
7
- module InstanceMethods
8
- def reload_connection()
9
- set_connection() if have_a_valid_shard?
10
- end
11
-
12
- def update_attribute(name, value)
13
- reload_connection()
14
- super(name, value)
15
- end
16
-
17
- def update_attributes(attributes)
18
- reload_connection()
19
- super(attributes)
8
+ module SharedMethods
9
+ def clean_table_name
10
+ self.reset_table_name() if self != ActiveRecord::Base && self.respond_to?(:reset_table_name)
20
11
  end
12
+
13
+ def using(shard, &block)
14
+ hijack_connection()
15
+ clean_table_name()
21
16
 
22
- def update_attributes!(attributes)
23
- reload_connection()
24
- super(attributes)
25
- end
17
+ if block_given?
18
+ self.connection.run_queries_on_shard(shard, &block)
19
+ else
20
+ hijack_initializer()
21
+ self.connection.current_shard = shard
22
+ self.connection.using_enabled = true
26
23
 
27
- def reload
28
- reload_connection()
29
- super
24
+ return self
25
+ end
30
26
  end
31
-
27
+
32
28
  def hijack_initializer()
33
29
  attr_accessor :current_shard
34
30
  after_initialize :set_current_shard
@@ -36,12 +32,10 @@ module Octopus::Model
36
32
  before_destroy :set_connection
37
33
 
38
34
  def set_current_shard
39
- if self.class.respond_to?(:connection_proxy) && self.respond_to?(:current_shard)
40
- if self.new_record?
41
- self.current_shard = self.class.connection_proxy.current_shard
42
- else
43
- self.current_shard = self.class.connection_proxy.last_current_shard
44
- end
35
+ if new_record?
36
+ self.current_shard = self.class.connection_proxy.current_shard
37
+ else
38
+ self.current_shard = self.class.connection_proxy.last_current_shard
45
39
  end
46
40
  end
47
41
  end
@@ -58,67 +52,30 @@ module Octopus::Model
58
52
  end
59
53
  end
60
54
  end
55
+ end
61
56
 
62
- def using(shard, &block)
63
- hijack_connection()
64
- clean_table_name()
65
-
66
- if block_given?
67
- self.connection_proxy.run_query_on_shard(shard, &block)
68
- else
69
- hijack_initializer()
70
- self.connection_proxy.current_shard = shard
71
- self.connection_proxy.using_enabled = true
72
-
73
- return self
74
- end
75
- end
76
-
77
- def have_a_valid_shard?
78
- self.respond_to?(:current_shard) && self.current_shard != nil
79
- end
80
-
57
+ module InstanceMethods
58
+ include SharedMethods
59
+
81
60
  def set_connection(*args)
82
61
  if(args.size == 1)
83
62
  arg = args.first
84
63
  arg.current_shard = self.current_shard if arg.respond_to?(:current_shard) && have_a_valid_shard?
85
64
  end
86
65
 
87
- self.class.connection_proxy.current_shard = self.current_shard if have_a_valid_shard?
66
+ self.connection.current_shard = self.current_shard if have_a_valid_shard?
88
67
  end
89
-
90
- def clean_table_name
91
- self.reset_table_name() if self != ActiveRecord::Base && self.respond_to?(:reset_table_name)
68
+
69
+ def have_a_valid_shard?
70
+ self.respond_to?(:current_shard) && self.current_shard != nil
92
71
  end
93
72
  end
94
73
 
95
- include InstanceMethods
96
-
97
- def replicated_model()
98
- write_inheritable_attribute(:replicated, true)
99
- end
100
-
101
- def has_many(association_id, options = {}, &extension)
102
- default_octopus_opts(options)
103
- super(association_id, options, &extension)
104
- end
105
-
106
- def has_and_belongs_to_many(association_id, options = {}, &extension)
107
- default_octopus_opts(options)
108
- super(association_id, options, &extension)
109
- end
110
-
111
- def default_octopus_opts(options)
112
- if options[:before_add].is_a?(Array)
113
- options[:before_add] << :set_connection
114
- else
115
- options[:before_add] = :set_connection
116
- end
74
+ module ClassMethods
75
+ include SharedMethods
117
76
 
118
- if options[:before_remove].is_a?(Array)
119
- options[:before_remove] << :set_connection
120
- else
121
- options[:before_remove] = :set_connection
77
+ def replicated_model()
78
+ write_inheritable_attribute(:replicated, true)
122
79
  end
123
80
  end
124
81
  end
@@ -0,0 +1,27 @@
1
+ module Octopus::Persistence
2
+ def reload_connection()
3
+ set_connection() if have_a_valid_shard?
4
+ end
5
+
6
+ def update_attribute(name, value)
7
+ reload_connection()
8
+ super(name, value)
9
+ end
10
+
11
+ def update_attributes(attributes)
12
+ reload_connection()
13
+ super(attributes)
14
+ end
15
+
16
+ def update_attributes!(attributes)
17
+ reload_connection()
18
+ super(attributes)
19
+ end
20
+
21
+ def reload
22
+ reload_connection()
23
+ super
24
+ end
25
+ end
26
+
27
+ ActiveRecord::Base.send(:include, Octopus::Persistence)
@@ -1,25 +1,17 @@
1
- require "set"
2
-
3
1
  class Octopus::Proxy
4
- attr_accessor :shards, :block, :current_model, :current_shard, :groups, :current_group, :replicated, :slaves_list, :using_enabled, :last_current_shard
5
-
6
- delegate :increment_open_transactions, :decrement_open_transactions, :to => :select_connection
2
+ attr_accessor :current_model, :current_shard, :current_group, :block, :using_enabled, :last_current_shard
7
3
 
8
4
  def initialize(config)
5
+ initialize_shards(config)
6
+ initialize_replication() if config[Octopus.env()]["replicated"]
7
+ end
8
+
9
+ def initialize_shards(config)
9
10
  @shards = {}
10
11
  @groups = {}
11
- @replicated = config[Octopus.env()]["replicated"]
12
12
  @shards[:master] = ActiveRecord::Base.connection_pool()
13
13
  @current_shard = :master
14
14
 
15
- initialize_shards(config)
16
-
17
- if @replicated
18
- initialize_replication()
19
- end
20
- end
21
-
22
- def initialize_shards(config)
23
15
  config[Octopus.env()]["shards"].each do |key, value|
24
16
  if value.has_key?("adapter")
25
17
  initialize_adapter(value['adapter'])
@@ -38,11 +30,10 @@ class Octopus::Proxy
38
30
  end
39
31
 
40
32
  def initialize_replication()
41
- @slaves_list = @shards.keys
42
- @slaves_list.delete(:master)
43
- @slaves_list = @slaves_list.map {|sym| sym.to_s}.sort
33
+ @replicated = true
34
+ @slaves_list = @shards.keys.map {|sym| sym.to_s}.sort
35
+ @slaves_list.delete('master')
44
36
  end
45
-
46
37
 
47
38
  def current_shard=(shard_symbol)
48
39
  if shard_symbol.is_a?(Array)
@@ -58,18 +49,14 @@ class Octopus::Proxy
58
49
  if group_symbol.is_a?(Array)
59
50
  group_symbol.each {|symbol| raise "Nonexistent Group Name: #{symbol}" if @groups[symbol].nil? }
60
51
  else
61
- raise "Nonexistent Group Name: #{group_symbol}" if @groups[group_symbol].nil? && !group_symbol.nil?
52
+ raise "Nonexistent Group Name: #{group_symbol}" if @groups[group_symbol].nil?
62
53
  end
63
54
 
64
55
  @current_group = group_symbol
65
56
  end
66
57
 
67
58
  def current_model=(model)
68
- if model.is_a?(ActiveRecord::Base)
69
- @current_model = model.class
70
- else
71
- @current_model = model
72
- end
59
+ @current_model = model.is_a?(ActiveRecord::Base) ? model.class : model
73
60
  end
74
61
 
75
62
  def select_connection()
@@ -77,11 +64,7 @@ class Octopus::Proxy
77
64
  end
78
65
 
79
66
  def shard_name
80
- if(current_shard.is_a?(Array))
81
- current_shard.first
82
- else
83
- current_shard
84
- end
67
+ current_shard.is_a?(Array) ? current_shard.first : current_shard
85
68
  end
86
69
 
87
70
  def add_transaction_record(record)
@@ -97,7 +80,7 @@ class Octopus::Proxy
97
80
  self.send_transaction_to_multiple_groups(options, &block)
98
81
  elsif should_send_queries_to_a_group_of_shards?
99
82
  self.send_transaction_to_multiple_shards(@groups[current_group], options, &block)
100
- self.current_group = nil
83
+ @current_group = nil
101
84
  else
102
85
  select_connection.transaction(options, &block)
103
86
  end
@@ -123,10 +106,11 @@ class Octopus::Proxy
123
106
  end
124
107
  end
125
108
 
126
- def run_query_on_shard(shard, &block)
109
+ def run_queries_on_shard(shard, &block)
127
110
  older_shard = self.current_shard
128
111
  self.block = true
129
112
  self.current_shard = shard
113
+
130
114
  begin
131
115
  yield
132
116
  ensure
@@ -142,7 +126,6 @@ class Octopus::Proxy
142
126
 
143
127
  def initialize_adapter(adapter)
144
128
  begin
145
- require 'rubygems'
146
129
  gem "activerecord-#{adapter}-adapter"
147
130
  require "active_record/connection_adapters/#{adapter}_adapter"
148
131
  rescue LoadError
@@ -155,7 +138,7 @@ class Octopus::Proxy
155
138
  end
156
139
 
157
140
  def should_clean_connection?(method)
158
- method.to_s =~ /insert|select/ && !should_send_queries_to_multiple_shards? && !self.current_group && !replicated
141
+ method.to_s =~ /insert|select/ && !should_send_queries_to_multiple_shards? && !self.current_group && !@replicated
159
142
  end
160
143
 
161
144
  def should_send_queries_to_multiple_shards?
@@ -199,8 +182,8 @@ class Octopus::Proxy
199
182
 
200
183
  if current_model.read_inheritable_attribute(:replicated)
201
184
  if !using_enabled
202
- self.current_shard = slaves_list.shift.to_sym
203
- slaves_list << self.current_shard
185
+ self.current_shard = @slaves_list.shift.to_sym
186
+ @slaves_list << self.current_shard
204
187
  end
205
188
  else
206
189
  self.current_shard = :master
@@ -1,5 +1,4 @@
1
1
  require 'rubygems'
2
2
  require 'active_record'
3
- require "pg"
4
3
 
5
4
  ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => "octopus_shard1", :username => "root", :password => "")
@@ -145,7 +145,7 @@ describe Octopus::Model do
145
145
  describe "#replicated_model method" do
146
146
  it "should be replicated" do
147
147
  using_enviroment :production_replicated do
148
- ActiveRecord::Base.connection_proxy.replicated.should be_true
148
+ ActiveRecord::Base.connection_proxy.instance_variable_get(:@replicated).should be_true
149
149
  end
150
150
  end
151
151
 
@@ -7,15 +7,15 @@ describe Octopus::Proxy do
7
7
 
8
8
  describe "creating a new instance" do
9
9
  it "should initialize all shards and groups" do
10
- @proxy.shards.keys.to_set.should == [:postgresql_shard, :alone_shard, :aug2011, :canada, :brazil, :aug2009, :russia, :aug2010, :master].to_set
11
- @proxy.groups.should == {:country_shards=>[:canada, :brazil, :russia], :history_shards=>[:aug2009, :aug2010, :aug2011]}
10
+ @proxy.instance_variable_get(:@shards).keys.to_set.should == [:postgresql_shard, :alone_shard, :aug2011, :canada, :brazil, :aug2009, :russia, :aug2010, :master].to_set
11
+ @proxy.instance_variable_get(:@groups).should == {:country_shards=>[:canada, :brazil, :russia], :history_shards=>[:aug2009, :aug2010, :aug2011]}
12
12
  end
13
13
 
14
14
  it "should initialize the block attribute as false" do
15
15
  @proxy.block.should be_false
16
16
  end
17
17
  it "should initialize replicated attribute as false" do
18
- @proxy.replicated.should be_false
18
+ @proxy.instance_variable_get(:@replicated).should be_false
19
19
  end
20
20
 
21
21
  describe "should raise error if you have duplicated shard names" do
@@ -48,12 +48,12 @@ describe Octopus::Proxy do
48
48
 
49
49
  describe "should return the connection based on shard_name" do
50
50
  it "when current_shard is empty" do
51
- @proxy.select_connection().should == @proxy.shards[:master].connection()
51
+ @proxy.select_connection().should == @proxy.instance_variable_get(:@shards)[:master].connection()
52
52
  end
53
53
 
54
54
  it "when current_shard is a single shard" do
55
55
  @proxy.current_shard = :canada
56
- @proxy.select_connection().should == @proxy.shards[:canada].connection()
56
+ @proxy.select_connection().should == @proxy.instance_variable_get(:@shards)[:canada].connection()
57
57
  end
58
58
  end
59
59
  end
@@ -10,7 +10,7 @@ describe "when the database is replicated" do
10
10
  end
11
11
 
12
12
  it "should initialize the list of shards" do
13
- @proxy.slaves_list.should == ["slave1", "slave2", "slave3", "slave4"]
13
+ @proxy.instance_variable_get(:@slaves_list).should == ["slave1", "slave2", "slave3", "slave4"]
14
14
  end
15
15
 
16
16
  it "should send all writes/reads queries to master when you have a replicated model" do
@@ -1,5 +1,5 @@
1
1
  def clean_all_shards()
2
- ActiveRecord::Base.using(:master).connection.shards.keys.each do |shard_symbol|
2
+ ActiveRecord::Base.using(:master).connection.instance_variable_get(:@shards).keys.each do |shard_symbol|
3
3
  ['schema_migrations', 'users', 'clients', 'cats', 'items', 'keyboards', 'computers', 'permissions_roles', 'roles', 'permissions', 'assignments', 'projects', 'programmers'].each do |tables|
4
4
  ActiveRecord::Base.using(shard_symbol).connection.execute("DELETE FROM #{tables};")
5
5
  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: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
9
+ - 6
10
+ version: 0.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Thiago Pradi
@@ -75,6 +75,7 @@ files:
75
75
  - lib/octopus/has_and_belongs_to_many_association.rb
76
76
  - lib/octopus/migration.rb
77
77
  - lib/octopus/model.rb
78
+ - lib/octopus/persistence.rb
78
79
  - lib/octopus/proxy.rb
79
80
  - rails/init.rb
80
81
  - spec/config/shards.yml