master_slave_adapter_tcurdt 0.0.2 → 0.0.3

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.
@@ -15,9 +15,11 @@ ActiveRecord::Base.class_eval do
15
15
  # ActiveRecord::Base.with_master do
16
16
  # User.count( :conditions => { :login => 'testuser' } )
17
17
  # end
18
- def with_master
19
- ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.with_master do
20
- yield
18
+ def with_master(&block)
19
+ if connection.respond_to? :with_master
20
+ connection.with_master(&block)
21
+ else
22
+ raise "no with_master"
21
23
  end
22
24
  end
23
25
 
@@ -26,9 +28,11 @@ ActiveRecord::Base.class_eval do
26
28
  # ActiveRecord::Base.with_slave do
27
29
  # User.count( :conditions => { :login => 'testuser' } )
28
30
  # end
29
- def with_slave
30
- ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.with_slave do
31
- yield
31
+ def with_slave(&block)
32
+ if connection.respond_to? :with_slave
33
+ connection.with_slave(&block)
34
+ else
35
+ raise "no with_slave"
32
36
  end
33
37
  end
34
38
 
@@ -39,11 +43,25 @@ ActiveRecord::Base.class_eval do
39
43
  # consistency = ActiveRecord::Base.with_consistency(consistency) do
40
44
  # User.count( :conditions => { :login => 'testuser' } )
41
45
  # end
42
- def with_consistency(consistency)
43
- ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.with_consistency(consistency) do
44
- yield
46
+ def with_consistency(clock, &block)
47
+ if connection.respond_to? :with_consistency
48
+ connection.with_consistency(clock, &block)
49
+ else
50
+ raise "no with_consistency"
51
+ end
52
+ end
53
+
54
+ def transaction_with_master(*args, &block)
55
+ if connection.respond_to? :transaction
56
+ connection.transaction do
57
+ transaction_without_master(*args, &block)
58
+ end
59
+ else
60
+ transaction_without_master(*args, &block)
45
61
  end
46
62
  end
63
+ alias_method_chain :transaction, :master
64
+
47
65
 
48
66
  def master_slave_connection( config )
49
67
  config = config.symbolize_keys
@@ -66,7 +84,7 @@ ActiveRecord::Base.class_eval do
66
84
 
67
85
  end
68
86
 
69
- ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.new( config )
87
+ ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.new(config)
70
88
  end
71
89
 
72
90
  def columns_with_master
@@ -74,9 +92,7 @@ ActiveRecord::Base.class_eval do
74
92
  columns_without_master
75
93
  end
76
94
  end
77
-
78
95
  alias_method_chain :columns, :master
79
96
 
80
97
  end
81
-
82
98
  end
@@ -1,13 +1,12 @@
1
1
  module ActiveRecord
2
-
3
2
  module ConnectionAdapters
4
-
5
3
  class MasterSlaveAdapter
6
4
 
7
5
  class Clock
8
6
  include Comparable
9
7
  attr_reader :file, :position
10
8
  def initialize(file, position)
9
+ raise ArgumentError, "file and postion may not be nil" if file.nil? || position.nil?
11
10
  @file, @position = file, position.to_i
12
11
  end
13
12
  def <=>(other)
@@ -19,7 +18,7 @@ module ActiveRecord
19
18
  def self.zero
20
19
  @zero ||= Clock.new('', 0)
21
20
  end
22
- end
21
+ end
23
22
 
24
23
  SELECT_METHODS = [ :select_all, :select_one, :select_rows, :select_value, :select_values ]
25
24
 
@@ -70,12 +69,6 @@ module ActiveRecord
70
69
  end
71
70
  end
72
71
 
73
- def commit_db_transaction()
74
- on_write do
75
- self.master_connection.commit_db_transaction()
76
- end
77
- end
78
-
79
72
  def reconnect!
80
73
  @active = true
81
74
  self.connections.each { |c| c.reconnect! }
@@ -102,6 +95,22 @@ module ActiveRecord
102
95
  connect_to_slave
103
96
  end
104
97
 
98
+ def current_connection=(stack)
99
+ Thread.current[:master_slave_connection] = stack
100
+ end
101
+
102
+ def current_connection
103
+ Thread.current[:master_slave_connection] || []
104
+ end
105
+
106
+ def current_clock=(stack)
107
+ Thread.current[:master_slave_clock] = stack
108
+ end
109
+
110
+ def current_clock
111
+ Thread.current[:master_slave_clock] || []
112
+ end
113
+
105
114
  def connections
106
115
  [ @master_connection, @slave_connection ].compact
107
116
  end
@@ -117,39 +126,42 @@ module ActiveRecord
117
126
  end
118
127
  end
119
128
 
120
- class << self
121
-
122
- def with_master
123
- Thread.current[:master_slave_select_connection] = [ :master ] + (Thread.current[:master_slave_select_connection]||[])
124
- result = yield
125
- Thread.current[:master_slave_select_connection] = Thread.current[:master_slave_select_connection].drop(1)
126
- result
127
- end
128
-
129
- def with_slave
130
- Thread.current[:master_slave_select_connection] = [ :slave ] + (Thread.current[:master_slave_select_connection]||[])
131
- result = yield
132
- Thread.current[:master_slave_select_connection] = Thread.current[:master_slave_select_connection].drop(1)
133
- result
134
- end
135
-
129
+ def with_master
130
+ self.current_connection = [ :master ] + self.current_connection
131
+ result = yield
132
+ self.current_connection = self.current_connection.drop(1)
133
+ result
134
+ end
136
135
 
137
- def with_consistency(clock)
138
- raise ArgumentError, "consistency cannot be nil" if !clock
136
+ def with_slave
137
+ self.current_connection = [ :slave ] + self.current_connection
138
+ result = yield
139
+ self.current_connection = self.current_connection.drop(1)
140
+ result
141
+ end
139
142
 
140
- Thread.current[:master_slave_select_connection] = [ nil ] + (Thread.current[:master_slave_select_connection]||[])
141
- Thread.current[:master_slave_clock] = [ clock || Clock::zero ] + (Thread.current[:master_slave_clock]||[])
143
+ def with_consistency(clock)
144
+ raise ArgumentError, "consistency cannot be nil" if clock.nil?
145
+ self.current_connection = [ nil ] + self.current_connection
146
+ self.current_clock = [ clock ] + self.current_clock
147
+ yield
148
+ result = current_clock[0]
149
+ self.current_clock = self.current_clock.drop(1)
150
+ self.current_connection = self.current_connection.drop(1)
151
+ result
152
+ end
142
153
 
143
- yield
144
- result = Thread.current[:master_slave_clock][0]
154
+ def transaction(*args)
155
+ puts "<transaction"
156
+ yield
157
+ puts "</transaction"
158
+ update_clock
159
+ end
145
160
 
146
- Thread.current[:master_slave_clock] = Thread.current[:master_slave_clock].drop(1)
147
- Thread.current[:master_slave_select_connection] = Thread.current[:master_slave_select_connection].drop(1)
148
- result
149
- end
161
+ class << self
150
162
 
151
163
  def reset!
152
- Thread.current[:master_slave_select_connection] = nil
164
+ Thread.current[:master_slave_connection] = nil
153
165
  Thread.current[:master_slave_clock] = nil
154
166
  end
155
167
 
@@ -162,8 +174,8 @@ module ActiveRecord
162
174
  end
163
175
 
164
176
  def using_master?
165
- if Thread.current[:master_slave_select_connection]
166
- Thread.current[:master_slave_select_connection][0] == :master
177
+ if Thread.current[:master_slave_connection]
178
+ Thread.current[:master_slave_connection][0] == :master
167
179
  else
168
180
  # there is no wrapper so selects go to slave by default
169
181
  false
@@ -175,11 +187,12 @@ module ActiveRecord
175
187
  private
176
188
 
177
189
  def update_clock
190
+ puts " update clock"
178
191
  # update the clock, if there was problem keep using the old one
179
- Thread.current[:master_slave_clock][0] = master_clock || Thread.current[:master_slave_clock][0]
192
+ self.current_clock[0] = master_clock || self.current_clock[0]
180
193
  # it's a write so from now on we use the master connection
181
194
  # as replication is not likely to be that fast
182
- Thread.current[:master_slave_select_connection][0] = :master
195
+ self.current_connection[0] = :master
183
196
  end
184
197
 
185
198
  def on_write
@@ -213,13 +226,14 @@ module ActiveRecord
213
226
  end
214
227
 
215
228
  def select_connection
216
- connection_stack = Thread.current[:master_slave_select_connection] ||= []
217
- clock_stack = Thread.current[:master_slave_clock] ||= []
229
+ connection_stack = self.current_connection
230
+ clock_stack = self.current_clock
218
231
 
219
232
  # pick the right connection
220
233
  if MasterSlaveAdapter.master_forced? || @master_connection.open_transactions > 0
221
234
  connection_stack[0] = :master
222
235
  end
236
+
223
237
  connection_stack[0] ||= connection_for_clock(clock_stack[0])
224
238
 
225
239
  # return the current connection
@@ -231,13 +245,17 @@ module ActiveRecord
231
245
  end
232
246
 
233
247
  def master_clock
234
- if status = connect_to_master.select_one("SHOW MASTER STATUS")
248
+ puts " master clock"
249
+ connection = connect_to_master
250
+ if status = connection.uncached { connection.select_one("SHOW MASTER STATUS") }
235
251
  Clock.new(status['File'], status['Position'])
236
252
  end
237
253
  end
238
254
 
239
255
  def slave_clock
240
- if status = connect_to_slave.select_one("SHOW SLAVE STATUS")
256
+ puts " slave clock"
257
+ connection = connect_to_slave
258
+ if status = connection.uncached { connection.select_one("SHOW SLAVE STATUS") }
241
259
  Clock.new(status['Relay_Master_Log_File'], status['Exec_Master_Log_Pos'])
242
260
  end
243
261
  end
@@ -251,7 +269,5 @@ module ActiveRecord
251
269
  end
252
270
 
253
271
  end
254
-
255
272
  end
256
-
257
273
  end
@@ -1,3 +1,3 @@
1
1
  module MasterSlaveAdapter
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -42,6 +42,13 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
42
42
  @master_connection = ActiveRecord::Base._master
43
43
  @slave_connection = ActiveRecord::Base._slave
44
44
 
45
+ @master_connection.stub!(:uncached) do |block|
46
+ block.call
47
+ end
48
+ @slave_connection.stub!(:uncached) do |block|
49
+ block.call
50
+ end
51
+
45
52
  end
46
53
 
47
54
  after do
@@ -50,7 +57,6 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
50
57
 
51
58
  describe 'with common configuration' do
52
59
 
53
-
54
60
  before do
55
61
 
56
62
  @database_setup = {
@@ -241,7 +247,7 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
241
247
  if pos.instance_of? Fixnum
242
248
  pos = [ pos ]
243
249
  end
244
- values = pos.map { |p| { 'Master_Log_File' => '', 'Exec_Master_Log_Pos' => p } }
250
+ values = pos.map { |p| { 'Relay_Master_Log_File' => '', 'Exec_Master_Log_Pos' => p } }
245
251
  @slave_connection.should_receive('select_one').exactly(pos.length).with('SHOW SLAVE STATUS').and_return(*values)
246
252
  end
247
253
 
@@ -307,9 +313,9 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
307
313
  @master_connection.should_receive(method).with('testing').and_return(true)
308
314
  old_clock = zero
309
315
  new_clock = ActiveRecord::Base.with_consistency(old_clock) do
310
- ActiveRecord::Base.connection.send(method, 'testing')
311
- ActiveRecord::Base.connection.send('update', 'testing')
312
- ActiveRecord::Base.connection.send(method, 'testing')
316
+ ActiveRecord::Base.connection.send(method, 'testing') # slave
317
+ ActiveRecord::Base.connection.send('update', 'testing') # master
318
+ ActiveRecord::Base.connection.send(method, 'testing') # master
313
319
  end
314
320
  new_clock.should be_a(zero.class)
315
321
  new_clock.should > old_clock
@@ -317,6 +323,42 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
317
323
 
318
324
  end
319
325
 
326
+ it "should update the clock after a transaction" do
327
+ ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.reset!
328
+ slave_should_report_clock(0)
329
+ master_should_report_clock([0, 1, 1, 1, 1])
330
+ @slave_connection.should_receive('select_all').exactly(1).times.with('testing').and_return(true)
331
+ @master_connection.should_receive('update').exactly(3).times.with('testing').and_return(true)
332
+ # @master_connection.should_receive('transaction').and_return(true)
333
+ @master_connection.should_receive('select_all').exactly(5).times.with('testing').and_return(true)
334
+
335
+ old_clock = zero
336
+ new_clock = ActiveRecord::Base.with_consistency(old_clock) do
337
+ puts "slave: select"
338
+ ActiveRecord::Base.connection.send('select_all', 'testing') # slave s=0 m=0
339
+ puts "master: update"
340
+ ActiveRecord::Base.connection.send('update', 'testing') # master s=0 m=1
341
+ puts "master: select"
342
+ ActiveRecord::Base.connection.send('select_all', 'testing') # master s=0 m=1
343
+
344
+ ActiveRecord::Base.transaction do
345
+ puts "master: select"
346
+ ActiveRecord::Base.connection.send('select_all', 'testing') # master s=0 m=1
347
+ puts "master: update"
348
+ ActiveRecord::Base.connection.send('update', 'testing') # master s=0 m=1
349
+ puts "master: select"
350
+ ActiveRecord::Base.connection.send('select_all', 'testing') # master s=0 m=1
351
+ end
352
+
353
+ puts "master: select"
354
+ ActiveRecord::Base.connection.send('select_all', 'testing') # master s=0 m=2
355
+ puts "master: update"
356
+ ActiveRecord::Base.connection.send('update', 'testing') # master s=0 m=3
357
+ puts "master: select"
358
+ ActiveRecord::Base.connection.send('select_all', 'testing') # master s=0 m=3
359
+ end
360
+ end
361
+
320
362
  it "should do the right thing when nested inside with_consistency" do
321
363
  ActiveRecord::ConnectionAdapters::MasterSlaveAdapter.reset!
322
364
  slave_should_report_clock([ 0, 0 ])
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mauricio Linhares
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-30 00:00:00 +02:00
18
+ date: 2011-06-06 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency