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 +2 -2
- data/lib/multi_db/active_record_extensions.rb +3 -4
- data/lib/multi_db/connection_proxy.rb +30 -8
- data/multi_db.gemspec +2 -2
- data/spec/connection_proxy_spec.rb +44 -5
- data/spec/spec_helper.rb +2 -2
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -25,7 +25,7 @@ master database.
|
|
25
25
|
|
26
26
|
=== Caveats
|
27
27
|
|
28
|
-
* works
|
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
|
-
|
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(:
|
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
|
16
|
-
self.connection_proxy.with_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
|
-
|
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
|
-
|
97
|
-
self.
|
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
|
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
|
-
|
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
|
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.
|
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{
|
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
|
-
|
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
|
-
|
3
|
-
%w[tlattr_accessors active_record yaml erb
|
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.
|
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:
|
12
|
+
date: 2011-05-17 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|