master_slave_adapter_soundcloud 0.1.3 → 0.1.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/.gitignore +2 -0
- data/VERSION +1 -1
- data/lib/master_slave_adapter.rb +29 -10
- data/master_slave_adapter.gemspec +1 -1
- data/specs/specs.rb +57 -51
- metadata +4 -22
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/lib/master_slave_adapter.rb
CHANGED
@@ -47,8 +47,9 @@ module ActiveRecord
|
|
47
47
|
def massage(config)
|
48
48
|
config = config.symbolize_keys
|
49
49
|
skip = [ :adapter, :connection_adapter, :master, :slaves ]
|
50
|
-
defaults = config.
|
51
|
-
|
50
|
+
defaults = config.
|
51
|
+
reject { |k,_| skip.include?(k) }.
|
52
|
+
merge(:adapter => config.fetch(:connection_adapter))
|
52
53
|
([config.fetch(:master)] + config.fetch(:slaves, [])).map do |cfg|
|
53
54
|
cfg.symbolize_keys!.reverse_merge!(defaults)
|
54
55
|
end
|
@@ -142,7 +143,7 @@ module ActiveRecord
|
|
142
143
|
# try random slave, else fall back to master
|
143
144
|
slave = slave_connection!
|
144
145
|
conn =
|
145
|
-
if !open_transaction? &&
|
146
|
+
if !open_transaction? && slave_consistent?(slave, clock)
|
146
147
|
[ slave, :slave ]
|
147
148
|
else
|
148
149
|
[ master_connection, :master ]
|
@@ -264,8 +265,8 @@ module ActiveRecord
|
|
264
265
|
:delete_sql,
|
265
266
|
:sanitize_limit,
|
266
267
|
:to => :master_connection
|
267
|
-
delegate *ActiveRecord::ConnectionAdapters::SchemaStatements.instance_methods
|
268
|
-
:to => :master_connection
|
268
|
+
delegate *(ActiveRecord::ConnectionAdapters::SchemaStatements.instance_methods + [{
|
269
|
+
:to => :master_connection }])
|
269
270
|
# no clear interface contract:
|
270
271
|
delegate :tables, # commented in SchemaStatements
|
271
272
|
:truncate_table, # monkeypatching database_cleaner gem
|
@@ -298,8 +299,10 @@ module ActiveRecord
|
|
298
299
|
private :connection_for_read
|
299
300
|
|
300
301
|
# === doesn't really matter, but must be handled by underlying adapter
|
301
|
-
delegate *ActiveRecord::ConnectionAdapters::Quoting.instance_methods
|
302
|
-
:to => :current_connection
|
302
|
+
delegate *(ActiveRecord::ConnectionAdapters::Quoting.instance_methods + [{
|
303
|
+
:to => :current_connection }])
|
304
|
+
# issue #4: current_database is not supported by all adapters, though
|
305
|
+
delegate :current_database, :to => :current_connection
|
303
306
|
|
304
307
|
# UTIL ==================================================================
|
305
308
|
|
@@ -340,13 +343,18 @@ module ActiveRecord
|
|
340
343
|
end
|
341
344
|
end
|
342
345
|
|
343
|
-
def slave_clock(
|
344
|
-
conn ||= slave_connection!
|
346
|
+
def slave_clock(conn)
|
345
347
|
if status = conn.uncached { conn.select_one("SHOW SLAVE STATUS") }
|
346
|
-
Clock.new(status['Relay_Master_Log_File'], status['Exec_Master_Log_Pos'])
|
348
|
+
Clock.new(status['Relay_Master_Log_File'], status['Exec_Master_Log_Pos']).tap do |c|
|
349
|
+
set_last_seen_slave_clock(conn, c)
|
350
|
+
end
|
347
351
|
end
|
348
352
|
end
|
349
353
|
|
354
|
+
def slave_consistent?(conn, clock)
|
355
|
+
(get_last_seen_slave_clock(conn) || slave_clock(conn)).try(:>=, clock)
|
356
|
+
end
|
357
|
+
|
350
358
|
protected
|
351
359
|
|
352
360
|
def on_write
|
@@ -406,6 +414,17 @@ module ActiveRecord
|
|
406
414
|
def on_rollback_callbacks
|
407
415
|
Thread.current[:on_rollback_callbacks] ||= []
|
408
416
|
end
|
417
|
+
|
418
|
+
def get_last_seen_slave_clock(conn)
|
419
|
+
conn.instance_variable_get(:@last_seen_slave_clock)
|
420
|
+
end
|
421
|
+
|
422
|
+
def set_last_seen_slave_clock(conn, clock)
|
423
|
+
last_seen = get_last_seen_slave_clock(conn)
|
424
|
+
if last_seen.nil? || last_seen < clock
|
425
|
+
conn.instance_variable_set(:@last_seen_slave_clock, clock)
|
426
|
+
end
|
427
|
+
end
|
409
428
|
end
|
410
429
|
end
|
411
430
|
end
|
@@ -4,7 +4,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'master_slave_adapter_soundcloud'
|
6
6
|
s.version = File.read('VERSION').to_s
|
7
|
-
s.date = '2011-
|
7
|
+
s.date = '2011-08-23'
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = [ 'Mauricio Linhares', 'Torsten Curdt', 'Kim Altintop', 'Omid Aladini', 'SoundCloud' ]
|
10
10
|
s.email = %q{kim@soundcloud.com tcurdt@soundcloud.com omid@soundcloud.com}
|
data/specs/specs.rb
CHANGED
@@ -211,17 +211,17 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
211
211
|
def slave_should_report_clock(pos)
|
212
212
|
pos = Array(pos)
|
213
213
|
values = pos.map { |p| { 'Relay_Master_Log_File' => '', 'Exec_Master_Log_Pos' => p } }
|
214
|
-
slave_connection
|
215
|
-
|
216
|
-
|
214
|
+
slave_connection.
|
215
|
+
should_receive('select_one').exactly(pos.length).with('SHOW SLAVE STATUS').
|
216
|
+
and_return(*values)
|
217
217
|
end
|
218
218
|
|
219
219
|
def master_should_report_clock(pos)
|
220
220
|
pos = Array(pos)
|
221
221
|
values = pos.map { |p| { 'File' => '', 'Position' => p } }
|
222
|
-
master_connection
|
223
|
-
|
224
|
-
|
222
|
+
master_connection.
|
223
|
+
should_receive('select_one').exactly(pos.length).with('SHOW MASTER STATUS').
|
224
|
+
and_return(*values)
|
225
225
|
end
|
226
226
|
|
227
227
|
SelectMethods.each do |method|
|
@@ -287,26 +287,27 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
287
287
|
slave_should_report_clock(0)
|
288
288
|
master_should_report_clock([0, 1, 1])
|
289
289
|
|
290
|
-
slave_connection
|
291
|
-
|
292
|
-
|
290
|
+
slave_connection.
|
291
|
+
should_receive('select_all').exactly(1).times.with('testing').
|
292
|
+
and_return(true)
|
293
293
|
|
294
|
-
master_connection
|
295
|
-
|
296
|
-
|
297
|
-
master_connection
|
298
|
-
|
299
|
-
|
294
|
+
master_connection.
|
295
|
+
should_receive('update').exactly(3).times.with('testing').
|
296
|
+
and_return(true)
|
297
|
+
master_connection.
|
298
|
+
should_receive('select_all').exactly(5).times.with('testing').
|
299
|
+
and_return(true)
|
300
300
|
%w(begin_db_transaction
|
301
301
|
commit_db_transaction
|
302
302
|
increment_open_transactions
|
303
|
-
decrement_open_transactions
|
303
|
+
decrement_open_transactions
|
304
|
+
outside_transaction?).each do |txstmt|
|
304
305
|
master_connection.should_receive(txstmt).exactly(1).times
|
305
306
|
end
|
306
307
|
|
307
|
-
master_connection
|
308
|
-
|
309
|
-
|
308
|
+
master_connection.
|
309
|
+
should_receive('open_transactions').exactly(13).times.
|
310
|
+
and_return(
|
310
311
|
# adapter: with_consistency, select_all, update, select_all
|
311
312
|
0, 0, 0, 0,
|
312
313
|
# connection: transaction
|
@@ -341,10 +342,10 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
341
342
|
|
342
343
|
context "with nested with_consistency" do
|
343
344
|
it "should return the same clock if not writing and no lag" do
|
344
|
-
slave_should_report_clock(
|
345
|
-
slave_connection
|
346
|
-
|
347
|
-
|
345
|
+
slave_should_report_clock(0) # note: tests memoizing slave clock
|
346
|
+
slave_connection.
|
347
|
+
should_receive('select_one').exactly(3).times.with('testing').
|
348
|
+
and_return(true)
|
348
349
|
|
349
350
|
old_clock = zero
|
350
351
|
new_clock = ActiveRecord::Base.with_consistency(old_clock) do
|
@@ -358,13 +359,15 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
358
359
|
end
|
359
360
|
|
360
361
|
it "requesting a newer clock should return a new clock" do
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
362
|
+
adapter_connection.
|
363
|
+
should_receive('slave_consistent?').exactly(2).times.
|
364
|
+
and_return(true, false)
|
365
|
+
slave_connection.
|
366
|
+
should_receive('select_all').exactly(2).times.with('testing').
|
367
|
+
and_return(true)
|
368
|
+
master_connection.
|
369
|
+
should_receive('select_all').exactly(1).times.with('testing').
|
370
|
+
and_return(true)
|
368
371
|
|
369
372
|
start_clock = zero
|
370
373
|
inner_clock = zero
|
@@ -439,23 +442,24 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
439
442
|
end
|
440
443
|
|
441
444
|
def run_tx
|
442
|
-
adapter_connection
|
443
|
-
|
444
|
-
|
445
|
+
adapter_connection.
|
446
|
+
should_receive('master_clock').
|
447
|
+
and_return(Clock.new('', 1))
|
445
448
|
%w(begin_db_transaction
|
446
449
|
commit_db_transaction
|
447
450
|
increment_open_transactions
|
448
|
-
decrement_open_transactions
|
449
|
-
|
450
|
-
|
451
|
+
decrement_open_transactions
|
452
|
+
outside_transaction?).each do |txstmt|
|
453
|
+
master_connection.
|
454
|
+
should_receive(txstmt).exactly(1).times
|
451
455
|
end
|
452
|
-
master_connection
|
453
|
-
|
454
|
-
|
456
|
+
master_connection.
|
457
|
+
should_receive('open_transactions').exactly(4).times.
|
458
|
+
and_return(0, 1, 0, 0)
|
455
459
|
|
456
|
-
master_connection
|
457
|
-
|
458
|
-
|
460
|
+
master_connection.
|
461
|
+
should_receive('update').with('testing').
|
462
|
+
and_return(true)
|
459
463
|
|
460
464
|
ActiveRecord::Base.transaction do
|
461
465
|
adapter_connection.send('update', 'testing')
|
@@ -467,15 +471,17 @@ describe ActiveRecord::ConnectionAdapters::MasterSlaveAdapter do
|
|
467
471
|
rollback_db_transaction
|
468
472
|
increment_open_transactions
|
469
473
|
decrement_open_transactions).each do |txstmt|
|
470
|
-
master_connection
|
471
|
-
|
472
|
-
end
|
473
|
-
master_connection
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
474
|
+
master_connection.
|
475
|
+
should_receive(txstmt).exactly(1).times
|
476
|
+
end
|
477
|
+
master_connection.
|
478
|
+
should_receive('outside_transaction?').exactly(2).times
|
479
|
+
master_connection.
|
480
|
+
should_receive('open_transactions').exactly(3).times.
|
481
|
+
and_return(0, 1, 0)
|
482
|
+
master_connection.
|
483
|
+
should_receive('update').with('testing').
|
484
|
+
and_return(true)
|
479
485
|
|
480
486
|
ActiveRecord::Base.transaction do
|
481
487
|
adapter_connection.send('update', 'testing')
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: master_slave_adapter_soundcloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 3
|
9
|
-
version: 0.1.3
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.6
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Mauricio Linhares
|
@@ -18,7 +14,7 @@ autorequire:
|
|
18
14
|
bindir: bin
|
19
15
|
cert_chain: []
|
20
16
|
|
21
|
-
date: 2011-
|
17
|
+
date: 2011-08-23 00:00:00 +02:00
|
22
18
|
default_executable:
|
23
19
|
dependencies:
|
24
20
|
- !ruby/object:Gem::Dependency
|
@@ -29,8 +25,6 @@ dependencies:
|
|
29
25
|
requirements:
|
30
26
|
- - ">="
|
31
27
|
- !ruby/object:Gem::Version
|
32
|
-
segments:
|
33
|
-
- 0
|
34
28
|
version: "0"
|
35
29
|
type: :development
|
36
30
|
version_requirements: *id001
|
@@ -42,10 +36,6 @@ dependencies:
|
|
42
36
|
requirements:
|
43
37
|
- - "="
|
44
38
|
- !ruby/object:Gem::Version
|
45
|
-
segments:
|
46
|
-
- 2
|
47
|
-
- 3
|
48
|
-
- 9
|
49
39
|
version: 2.3.9
|
50
40
|
type: :runtime
|
51
41
|
version_requirements: *id002
|
@@ -82,25 +72,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
72
|
requirements:
|
83
73
|
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
|
-
segments:
|
86
|
-
- 1
|
87
|
-
- 9
|
88
|
-
- 2
|
89
75
|
version: 1.9.2
|
90
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
77
|
none: false
|
92
78
|
requirements:
|
93
79
|
- - ">="
|
94
80
|
- !ruby/object:Gem::Version
|
95
|
-
segments:
|
96
|
-
- 1
|
97
|
-
- 3
|
98
|
-
- 7
|
99
81
|
version: 1.3.7
|
100
82
|
requirements: []
|
101
83
|
|
102
84
|
rubyforge_project:
|
103
|
-
rubygems_version: 1.
|
85
|
+
rubygems_version: 1.5.0
|
104
86
|
signing_key:
|
105
87
|
specification_version: 3
|
106
88
|
summary: Replication Aware Master/Slave Database Adapter for Rails/ActiveRecord
|