multi_db 0.2.2 → 0.3.0

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