ar_mysql_flexmaster 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
13
  gem.name = "ar_mysql_flexmaster"
14
14
  gem.require_paths = ["lib"]
15
- gem.version = "0.2.2"
15
+ gem.version = "0.3.0"
16
16
 
17
17
  gem.add_runtime_dependency("mysql2")
18
18
  gem.add_runtime_dependency("activerecord")
data/bin/master_cut CHANGED
@@ -88,7 +88,7 @@ def preflight_check
88
88
  fail("slave is delayed") if slave_info['Seconds_Behind_Master'].nil? || slave_info['Seconds_Behind_Master'] > 0
89
89
 
90
90
  masters_slave_info = cx.query("show slave status").first
91
- if $rehome_master && masters_slave_info.nil? || masters_slave_info['Master_User'] == 'test'
91
+ if $rehome_master && (masters_slave_info.nil? || masters_slave_info['Master_User'] == 'test')
92
92
  fail("I can't rehome the original master -- it has no slave user or password.")
93
93
  end
94
94
 
@@ -47,25 +47,34 @@ module ActiveRecord
47
47
 
48
48
  def begin_db_transaction
49
49
  if !cx_correct? && open_transactions == 0
50
- refind_correct_host
50
+ refind_correct_host!
51
51
  end
52
52
  super
53
53
  end
54
54
 
55
55
  def execute(sql, name = nil)
56
56
  if open_transactions == 0 && sql =~ /^(INSERT|UPDATE|DELETE|ALTER|CHANGE)/ && !cx_correct?
57
- refind_correct_host
57
+ refind_correct_host!
58
58
  else
59
59
  @select_counter += 1
60
60
  if (@select_counter % CHECK_EVERY_N_SELECTS == 0) && !cx_correct?
61
61
  # on select statements, check every 10 times to see if we need to switch masters,
62
- # but don't hold off anything if we fail
63
- refind_correct_host(1, 0)
62
+ # but don't sleep, and if existing connection isn't correct, go ahead anyway.
63
+ cx = find_correct_host
64
+ @connection = cx if cx
64
65
  end
65
66
  end
66
67
  super
67
68
  end
68
69
 
70
+ def current_host
71
+ @connection.query_options[:host]
72
+ end
73
+
74
+ def current_port
75
+ @connection.query_options[:port]
76
+ end
77
+
69
78
  private
70
79
 
71
80
  def connect
@@ -90,11 +99,12 @@ module ActiveRecord
90
99
  collected_errors.map { |e| "#{e.class.name}: #{e.message}" }.uniq.join(",")
91
100
  end
92
101
 
93
- def refind_correct_host(tries = nil, sleep_interval = nil)
102
+ def refind_correct_host!
94
103
  clear_collected_errors!
95
104
 
96
- tries ||= @tx_hold_timeout.to_f / 0.1
97
- sleep_interval ||= 0.1
105
+ sleep_interval = 0.1
106
+ tries = @tx_hold_timeout.to_f / sleep_interval
107
+
98
108
  tries.to_i.times do
99
109
  cx = find_correct_host
100
110
  if cx
@@ -128,7 +138,6 @@ module ActiveRecord
128
138
  chosen_cx = correct_cxs.first
129
139
  else
130
140
  # nothing read-write, or too many read-write
131
- # (should we manually close the connections?)
132
141
  if correct_cxs.size > 1
133
142
  collected_errors << TooManyMastersException.new("found #{correct_cxs.size} read-write servers")
134
143
  else
@@ -121,6 +121,18 @@ class TestArFlexmaster < Test::Unit::TestCase
121
121
  assert !main_connection_is_original_master?
122
122
  end
123
123
 
124
+ # there's a small window in which the old master is read-only but the new slave hasn't come online yet.
125
+ # Allow side-effect free statements to continue.
126
+ def test_should_not_crash_selects_in_the_double_read_only_window
127
+ ActiveRecord::Base.connection
128
+ $mysql_master.set_rw(false)
129
+ $mysql_slave.set_rw(false)
130
+ assert main_connection_is_original_master?
131
+ 100.times do
132
+ u = User.first
133
+ end
134
+ end
135
+
124
136
  def test_should_choose_a_random_slave_connection
125
137
  h = {}
126
138
  10.times do
@@ -131,6 +143,12 @@ class TestArFlexmaster < Test::Unit::TestCase
131
143
  assert_equal 2, h.size
132
144
  end
133
145
 
146
+ def test_should_expose_the_current_master_and_port
147
+ cx = ActiveRecord::Base.connection
148
+ assert_equal "127.0.0.1", cx.current_host
149
+ assert_equal $mysql_master.port, cx.current_port
150
+ end
151
+
134
152
  def test_should_flip_the_slave_after_it_becomes_master
135
153
  UserSlave.first
136
154
  User.create!
@@ -38,3 +38,5 @@ $mysql_master.connection.query("CREATE DATABASE flexmaster_test")
38
38
  $mysql_master.connection.query("CREATE TABLE flexmaster_test.users (id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, name varchar(20))")
39
39
  $mysql_master.connection.query("INSERT INTO flexmaster_test.users set name='foo'")
40
40
 
41
+ $mysql_slave.set_rw(false)
42
+ sleep if __FILE__ == $0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_mysql_flexmaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-20 00:00:00.000000000 Z
12
+ date: 2013-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mysql2