multi_db 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -25,7 +25,7 @@ master database.
25
25
 
26
26
  === Caveats
27
27
 
28
- * works only with activerecord 2.1, 2.2 and 2.3
28
+ * works with activerecord 2.1, 2.2, 2.3, and 3.0
29
29
 
30
30
  === Install
31
31
 
@@ -259,7 +259,7 @@ If you haven't already, install the rspec gem, then create an empty database
259
259
  called "multi_db_test" (you might want to tweak the spec/config/database.yml).
260
260
  From the plugin directory, run:
261
261
 
262
- spec spec
262
+ rspec spec
263
263
 
264
264
 
265
265
  Copyright (c) 2008, Max Schoefmann <max (a) pragmatic-it de>
@@ -3,17 +3,16 @@ module MultiDb
3
3
  def self.included(base)
4
4
  base.send :include, InstanceMethods
5
5
  base.send :extend, ClassMethods
6
- base.alias_method_chain :reload, :master
7
6
  base.cattr_accessor :connection_proxy
8
7
  # handle subclasses which were defined by the framework or plugins
9
- base.send(:subclasses).each do |child|
8
+ base.send(:descendants).each do |child|
10
9
  child.hijack_connection
11
10
  end
12
11
  end
13
12
 
14
13
  module InstanceMethods
15
- def reload_with_master(*args, &block)
16
- self.connection_proxy.with_master { reload_without_master }
14
+ def reload(options = nil)
15
+ self.connection_proxy.with_master { super }
17
16
  end
18
17
  end
19
18
 
@@ -1,7 +1,9 @@
1
+ require 'active_record/connection_adapters/abstract/query_cache'
2
+
1
3
  module MultiDb
2
4
  class ConnectionProxy
3
- include QueryCacheCompat
4
5
  include ActiveRecord::ConnectionAdapters::QueryCache
6
+ include QueryCacheCompat
5
7
  extend ThreadLocalAccessors
6
8
 
7
9
  # Safe methods are those that should either go to the slave ONLY or go
@@ -37,6 +39,9 @@ module MultiDb
37
39
  # has to do this.
38
40
  # This will not affect failover if a master is unavailable.
39
41
  attr_accessor :sticky_slave
42
+
43
+ # if master should be the default db
44
+ attr_accessor :defaults_to_master
40
45
 
41
46
  # Replaces the connection of ActiveRecord::Base with a proxy and
42
47
  # establishes the connections to the slaves.
@@ -64,7 +69,7 @@ module MultiDb
64
69
  # production_slave_database_someserver:
65
70
  # These would be available later as MultiDb::SlaveDatabaseSomeserver
66
71
  def init_slaves
67
- returning([]) do |slaves|
72
+ [].tap do |slaves|
68
73
  ActiveRecord::Base.configurations.each do |name, values|
69
74
  if name.to_s =~ /#{self.environment}_(slave_database.*)/
70
75
  weight = if values['weight'].blank?
@@ -93,8 +98,14 @@ module MultiDb
93
98
  @slaves = scheduler.new(slaves)
94
99
  @master = master
95
100
  @reconnect = false
96
- self.current = @slaves.current
97
- self.master_depth = 0
101
+ @query_cache = {}
102
+ if self.class.defaults_to_master
103
+ self.current = @master
104
+ self.master_depth = 1
105
+ else
106
+ self.current = @slaves.current
107
+ self.master_depth = 0
108
+ end
98
109
  end
99
110
 
100
111
  def slave
@@ -104,14 +115,25 @@ module MultiDb
104
115
  def scheduler
105
116
  @slaves
106
117
  end
107
-
118
+
119
+
108
120
  def with_master
109
121
  self.current = @master
110
122
  self.master_depth += 1
111
123
  yield
112
124
  ensure
113
125
  self.master_depth -= 1
114
- self.current = slave if master_depth.zero?
126
+ self.current = slave if (master_depth <= 0)
127
+ end
128
+
129
+
130
+ def with_slave
131
+ self.current = slave
132
+ self.master_depth -= 1
133
+ yield
134
+ ensure
135
+ self.master_depth += 1
136
+ self.current = @master if (master_depth > 0)
115
137
  end
116
138
 
117
139
  def transaction(start_db_transaction = true, &block)
@@ -121,7 +143,7 @@ module MultiDb
121
143
  # Calls the method on master/slave and dynamically creates a new
122
144
  # method on success to speed up subsequent calls
123
145
  def method_missing(method, *args, &block)
124
- returning(send(target_method(method), method, *args, &block)) do
146
+ send(target_method(method), method, *args, &block).tap do
125
147
  create_delegation_method!(method)
126
148
  end
127
149
  end
@@ -129,7 +151,7 @@ module MultiDb
129
151
  # Switches to the next slave database for read operations.
130
152
  # Fails over to the master database if all slaves are unavailable.
131
153
  def next_reader!
132
- return unless master_depth.zero? # don't if in with_master block
154
+ return if master_depth > 0 # don't if in with_master block
133
155
  self.current = @slaves.next
134
156
  rescue Scheduler::NoMoreItems
135
157
  logger.warn "[MULTIDB] All slaves are blacklisted. Reading from master"
data/multi_db.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{multi_db}
5
- s.version = "0.2.2"
5
+ s.version = "0.3.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Maximilian Sch\303\266fmann"]
9
- s.date = %q{2009-03-11}
9
+ s.date = %q{2011-05-17}
10
10
  s.description = "Connection proxy for ActiveRecord for single master / multiple slave database deployments"
11
11
  s.email = "max@pragmatic-it.de"
12
12
  s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
@@ -31,10 +31,6 @@ describe MultiDb::ConnectionProxy do
31
31
  @slave3 = MultiDb::SlaveDatabase3.retrieve_connection
32
32
  @slave4 = MultiDb::SlaveDatabase4.retrieve_connection
33
33
  end
34
-
35
- after(:each) do
36
- ActiveRecord::Base.send :alias_method, :reload, :reload_without_master
37
- end
38
34
 
39
35
  it 'AR::B should respond to #connection_proxy' do
40
36
  ActiveRecord::Base.connection_proxy.should be_kind_of(MultiDb::ConnectionProxy)
@@ -284,6 +280,49 @@ describe MultiDb::ConnectionProxy do
284
280
  end
285
281
  end
286
282
 
287
- end # with alternative scheduler
283
+ describe "defaults_to_master" do
284
+ before do
285
+ MultiDb::ConnectionProxy.defaults_to_master = true
286
+ MultiDb::ConnectionProxy.setup!
287
+ @proxy = ActiveRecord::Base.connection_proxy
288
+ end
289
+
290
+ after do
291
+ MultiDb::ConnectionProxy.defaults_to_master = nil
292
+ end
293
+
294
+ it "sets the default database to master" do
295
+ @proxy.current.should == @proxy.master
296
+ end
297
+
298
+ it "is still master, when using with_master" do
299
+ @proxy.with_master do
300
+ @proxy.current.should == @proxy.master
301
+ end
302
+ end
303
+
304
+ it "switches to slave, when using with_slave" do
305
+ @proxy.with_slave do
306
+ @proxy.current.should_not == @proxy.master
307
+ end
308
+ end
309
+
310
+
311
+ it "keep right connection, when nesting with slave/master blocks" do
312
+ @proxy.with_slave do
313
+ @proxy.current.should_not == @proxy.master
314
+ @proxy.with_slave do
315
+ @proxy.current.should_not == @proxy.master
316
+ @proxy.with_master do
317
+ @proxy.current.should == @proxy.master
318
+ end
319
+ @proxy.current.should_not == @proxy.master
320
+ end
321
+ @proxy.current.should_not == @proxy.master
322
+ end
323
+ @proxy.current.should == @proxy.master
324
+ end
325
+ end
326
+ end
288
327
  end
289
328
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
- # gem 'activerecord', '2.2.2'
3
- %w[tlattr_accessors active_record yaml erb spec].each {|lib| require lib}
2
+ gem 'activerecord', '3.0.5'
3
+ %w[tlattr_accessors active_record yaml erb rspec logger].each {|lib| require lib}
4
4
 
5
5
  RAILS_ENV = ENV['RAILS_ENV'] = 'test'
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Maximilian Sch\xC3\xB6fmann"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-11 00:00:00 +01:00
12
+ date: 2011-05-17 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency