activerecord-mysql-reconnect 0.3.0 → 0.3.1
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.
- 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
|