ar-octopus 0.0.5 → 0.0.6

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 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