ar_mysql_flexmaster 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.
@@ -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