activerecord-mysql-reconnect 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/ChangeLog +4 -0
- data/README.md +7 -1
- data/lib/activerecord/mysql/reconnect.rb +20 -5
- data/lib/activerecord/mysql/reconnect/abstract_mysql_adapter_ext.rb +1 -1
- data/lib/activerecord/mysql/reconnect/base_ext.rb +11 -1
- data/lib/activerecord/mysql/reconnect/version.rb +1 -1
- data/spec/activerecord-mysql-reconnect_spec.rb +28 -1
- data/spec/spec_helper.rb +14 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmEzYzliYTU5N2ZmYjFkZGJjMGM0NmY3Yjc0NzhkYjhmM2YwZDBkNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzgwZjEzNmVjMmQwZTlhMDY4ZGU5MDY0MjZiNzJhODViMzBlMjYyYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Yjk2YWZlZDZiMDE0MzQ5ZWZkZjFjNDJkZjM2OTQxNDEwMWI0NjA5Zjg4NzRm
|
10
|
+
MjM4OWU3ZjdhNjY3MDkyMDMwYjIxNzVjZGM1Mzk1MGQ5NWQzMzI2NTFmMTg2
|
11
|
+
OTNmZDljMDViZmIyNmM5NDU0N2M2NWE0M2NmZTllNWFjOWJiMTk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmFkYWY5YmJkOThhYzBhN2JmOGZlOTM3NDM4Mzg1OGE2ZDJjYTU5YzVjZDcz
|
14
|
+
YWEzMDZlZDJiMThmM2QwYzcwMDg0YmZhZDA4YjEwNDA5YWE0ZmUxNTc4NGFk
|
15
|
+
NWU3OWM1ZTZiOTYzYTFlNjNkZjNhZDA1ZWJjNDZjMWFkZjRiNTc=
|
data/ChangeLog
CHANGED
data/README.md
CHANGED
@@ -91,11 +91,17 @@ MyApp::Application.configure do
|
|
91
91
|
config.active_record.enable_retry = true
|
92
92
|
config.active_record.execution_tries = 10 # times
|
93
93
|
config.active_record.execution_retry_wait = 1.5 # sec
|
94
|
-
config.active_record.
|
94
|
+
config.active_record.retry_mode = :rw # default: `:r`, valid values: `:r`, `:rw`, `:force`
|
95
95
|
...
|
96
96
|
ene
|
97
97
|
```
|
98
98
|
|
99
|
+
## Retry mode
|
100
|
+
|
101
|
+
* `:r` Retry only SELECT / SHOW / SET
|
102
|
+
* `:rw` Retry in all SQL, but does not retry if `Lost connection` has happened in write SQL
|
103
|
+
* `:force` Retry in all SQL
|
104
|
+
|
99
105
|
## Running tests on local
|
100
106
|
|
101
107
|
```sh
|
@@ -46,6 +46,9 @@ module Activerecord::Mysql::Reconnect
|
|
46
46
|
|
47
47
|
READ_SQL_REGEXP = /\A\s*(?:SELECT|SHOW|SET)\b/i
|
48
48
|
|
49
|
+
RETRY_MODES = [:r, :rw, :force]
|
50
|
+
DEFAULT_RETRY_MODE = :r
|
51
|
+
|
49
52
|
class << self
|
50
53
|
def execution_tries
|
51
54
|
ActiveRecord::Base.execution_tries || DEFAULT_EXECUTION_TRIES
|
@@ -59,8 +62,16 @@ module Activerecord::Mysql::Reconnect
|
|
59
62
|
!!ActiveRecord::Base.enable_retry
|
60
63
|
end
|
61
64
|
|
62
|
-
def
|
63
|
-
|
65
|
+
def retry_mode=(v)
|
66
|
+
unless RETRY_MODES.include?(v)
|
67
|
+
raise "Invalid retry_mode. Please set one of the following: #{RETRY_MODES.map {|i| i.inspect }.join(', ')}"
|
68
|
+
end
|
69
|
+
|
70
|
+
@activerecord_mysql_reconnect_retry_mode = v
|
71
|
+
end
|
72
|
+
|
73
|
+
def retry_mode
|
74
|
+
@activerecord_mysql_reconnect_retry_mode || DEFAULT_RETRY_MODE
|
64
75
|
end
|
65
76
|
|
66
77
|
def retryable(opts)
|
@@ -145,8 +156,8 @@ module Activerecord::Mysql::Reconnect
|
|
145
156
|
end
|
146
157
|
|
147
158
|
def should_handle?(e, opts = {})
|
148
|
-
sql
|
149
|
-
|
159
|
+
sql = opts[:sql]
|
160
|
+
retry_mode = opts[:retry_mode]
|
150
161
|
|
151
162
|
if without_retry?
|
152
163
|
return false
|
@@ -161,7 +172,11 @@ module Activerecord::Mysql::Reconnect
|
|
161
172
|
end
|
162
173
|
|
163
174
|
if sql and READ_SQL_REGEXP !~ sql
|
164
|
-
if
|
175
|
+
if retry_mode == :r
|
176
|
+
return false
|
177
|
+
end
|
178
|
+
|
179
|
+
if retry_mode != :force and Regexp.union(HANDLE_R_ERROR_MESSAGES) =~ e.message
|
165
180
|
return false
|
166
181
|
end
|
167
182
|
end
|
@@ -37,7 +37,7 @@ class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
|
|
37
37
|
sql_names = merge_transaction(sql, name)
|
38
38
|
},
|
39
39
|
:sql => sql,
|
40
|
-
:
|
40
|
+
:retry_mode => Activerecord::Mysql::Reconnect.retry_mode,
|
41
41
|
:connection => @connection
|
42
42
|
)
|
43
43
|
end
|
@@ -2,9 +2,19 @@ class ActiveRecord::Base
|
|
2
2
|
class_attribute :execution_tries, :instance_accessor => false
|
3
3
|
class_attribute :execution_retry_wait, :instance_accessor => false
|
4
4
|
class_attribute :enable_retry, :instance_accessor => false
|
5
|
-
|
5
|
+
|
6
|
+
RETRY_MODES = [:r, :rw, :force]
|
7
|
+
DEFAULT_RETRY_MODE = :r
|
6
8
|
|
7
9
|
class << self
|
10
|
+
def retry_mode=(v)
|
11
|
+
Activerecord::Mysql::Reconnect.retry_mode = v
|
12
|
+
end
|
13
|
+
|
14
|
+
def retry_mode
|
15
|
+
Activerecord::Mysql::Reconnect.retry_mode
|
16
|
+
end
|
17
|
+
|
8
18
|
def without_retry
|
9
19
|
Activerecord::Mysql::Reconnect.without_retry do
|
10
20
|
yield
|
@@ -243,10 +243,16 @@ describe 'activerecord-mysql-reconnect' do
|
|
243
243
|
end
|
244
244
|
|
245
245
|
it 'lost connection' do
|
246
|
+
sql = "INSERT INTO `employees` (`birth_date`, `emp_no`, `first_name`, `hire_date`, `last_name`) VALUES ('2014-01-09 03:22:25', 1, '' + sleep(15) + '', '2014-01-09 03:22:25', 'Tiger')"
|
247
|
+
|
248
|
+
expect {
|
249
|
+
ActiveRecord::Base.connection.execute(sql)
|
250
|
+
}.to_not raise_error
|
251
|
+
|
246
252
|
mysql2_error('Lost connection to MySQL server during query') do
|
247
253
|
expect {
|
248
254
|
th = thread_run {|do_stop|
|
249
|
-
ActiveRecord::Base.connection.execute(
|
255
|
+
ActiveRecord::Base.connection.execute(sql)
|
250
256
|
}
|
251
257
|
|
252
258
|
mysql_restart
|
@@ -254,4 +260,25 @@ describe 'activerecord-mysql-reconnect' do
|
|
254
260
|
}.to raise_error(ActiveRecord::StatementInvalid)
|
255
261
|
end
|
256
262
|
end
|
263
|
+
|
264
|
+
it 'force retry' do
|
265
|
+
sql = "INSERT INTO `employees` (`birth_date`, `emp_no`, `first_name`, `hire_date`, `last_name`) VALUES ('2014-01-09 03:22:25', 1, '' + sleep(15) + '', '2014-01-09 03:22:25', 'Tiger')"
|
266
|
+
|
267
|
+
expect {
|
268
|
+
ActiveRecord::Base.connection.execute(sql)
|
269
|
+
}.to_not raise_error
|
270
|
+
|
271
|
+
mysql2_error('Lost connection to MySQL server during query') do
|
272
|
+
expect {
|
273
|
+
th = thread_run {|do_stop|
|
274
|
+
force_retry do
|
275
|
+
ActiveRecord::Base.connection.execute(sql)
|
276
|
+
end
|
277
|
+
}
|
278
|
+
|
279
|
+
mysql_restart
|
280
|
+
th.join
|
281
|
+
}.to_not raise_error
|
282
|
+
end
|
283
|
+
end
|
257
284
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -49,11 +49,21 @@ end
|
|
49
49
|
|
50
50
|
def enable_read_only
|
51
51
|
begin
|
52
|
-
expect(ActiveRecord::Base.
|
53
|
-
ActiveRecord::Base.
|
52
|
+
expect(ActiveRecord::Base.retry_mode).to eq(:rw)
|
53
|
+
ActiveRecord::Base.retry_mode = :r
|
54
54
|
yield
|
55
55
|
ensure
|
56
|
-
ActiveRecord::Base.
|
56
|
+
ActiveRecord::Base.retry_mode = :rw
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def force_retry
|
61
|
+
begin
|
62
|
+
expect(ActiveRecord::Base.retry_mode).to eq(:rw)
|
63
|
+
ActiveRecord::Base.retry_mode = :force
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
ActiveRecord::Base.retry_mode = :rw
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
@@ -90,6 +100,6 @@ RSpec.configure do |config|
|
|
90
100
|
ActiveRecord::Base.logger.formatter = proc {|_, _, _, message| "#{message}\n" }
|
91
101
|
ActiveRecord::Base.enable_retry = true
|
92
102
|
ActiveRecord::Base.execution_tries = 10
|
93
|
-
ActiveRecord::Base.
|
103
|
+
ActiveRecord::Base.retry_mode = :rw
|
94
104
|
end
|
95
105
|
end
|