deadlock_retry 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/deadlock_retry.gemspec +4 -1
- data/lib/deadlock_retry.rb +32 -18
- data/test/deadlock_retry_test.rb +10 -4
- metadata +34 -30
data/CHANGELOG
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
deadlock_retry changes
|
2
2
|
|
3
|
+
== v1.1.2
|
4
|
+
|
5
|
+
* Exponential backoff, sleep 0, 1, 2, 4... seconds between retries.
|
6
|
+
* Support new syntax for InnoDB status in MySQL 5.5.
|
7
|
+
|
3
8
|
== v1.1.1 (2011-05-13)
|
4
9
|
|
5
10
|
* Conditionally log INNODB STATUS only if user has permission. (osheroff)
|
data/deadlock_retry.gemspec
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require './lib/deadlock_retry'
|
4
|
+
|
3
5
|
Gem::Specification.new do |s|
|
4
6
|
s.name = %q{deadlock_retry}
|
5
|
-
s.version =
|
7
|
+
s.version = DeadlockRetry::VERSION
|
6
8
|
s.authors = ["Jamis Buck", "Mike Perham"]
|
7
9
|
s.description = s.summary = %q{Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL}
|
8
10
|
s.email = %q{mperham@gmail.com}
|
9
11
|
s.files = `git ls-files`.split("\n")
|
10
12
|
s.homepage = %q{http://github.com/mperham/deadlock_retry}
|
11
13
|
s.require_paths = ["lib"]
|
14
|
+
s.add_development_dependency 'mocha'
|
12
15
|
end
|
data/lib/deadlock_retry.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
|
1
3
|
module DeadlockRetry
|
4
|
+
|
5
|
+
VERSION = '1.1.2'
|
6
|
+
|
2
7
|
def self.included(base)
|
3
8
|
base.extend(ClassMethods)
|
4
9
|
base.class_eval do
|
@@ -8,15 +13,7 @@ module DeadlockRetry
|
|
8
13
|
end
|
9
14
|
end
|
10
15
|
|
11
|
-
|
12
|
-
|
13
|
-
def self.innodb_status_available?
|
14
|
-
@@innodb_status_available
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.innodb_status_available=(bool)
|
18
|
-
@@innodb_status_available = bool
|
19
|
-
end
|
16
|
+
mattr_accessor :innodb_status_cmd
|
20
17
|
|
21
18
|
module ClassMethods
|
22
19
|
DEADLOCK_ERROR_MESSAGES = [
|
@@ -40,7 +37,8 @@ module DeadlockRetry
|
|
40
37
|
raise if retry_count >= MAXIMUM_RETRIES_ON_DEADLOCK
|
41
38
|
retry_count += 1
|
42
39
|
logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
|
43
|
-
log_innodb_status if DeadlockRetry.
|
40
|
+
log_innodb_status if DeadlockRetry.innodb_status_cmd
|
41
|
+
exponential_pause(retry_count)
|
44
42
|
retry
|
45
43
|
else
|
46
44
|
raise
|
@@ -50,25 +48,41 @@ module DeadlockRetry
|
|
50
48
|
|
51
49
|
private
|
52
50
|
|
51
|
+
WAIT_TIMES = [0, 1, 2, 4, 8, 16, 32]
|
52
|
+
|
53
|
+
def exponential_pause(count)
|
54
|
+
sec = WAIT_TIMES[count-1] || 32
|
55
|
+
# sleep 0, 1, 2, 4, ... seconds up to the MAXIMUM_RETRIES.
|
56
|
+
# Cap the pause time at 32 seconds.
|
57
|
+
sleep(sec) if sec != 0
|
58
|
+
end
|
59
|
+
|
53
60
|
def in_nested_transaction?
|
54
61
|
# open_transactions was added in 2.2's connection pooling changes.
|
55
62
|
connection.open_transactions != 0
|
56
63
|
end
|
57
64
|
|
58
65
|
def show_innodb_status
|
59
|
-
self.connection.select_value(
|
66
|
+
self.connection.select_value(DeadlockRetry.innodb_status_cmd)
|
60
67
|
end
|
61
68
|
|
62
69
|
# Should we try to log innodb status -- if we don't have permission to,
|
63
70
|
# we actually break in-flight transactions, silently (!)
|
64
71
|
def check_innodb_status_available
|
65
|
-
return unless DeadlockRetry.
|
72
|
+
return unless DeadlockRetry.innodb_status_cmd == nil
|
66
73
|
|
67
74
|
begin
|
68
|
-
|
69
|
-
|
75
|
+
mysql_version = self.connection.execute('show variables like \'version\'').to_a[0][1]
|
76
|
+
cmd = if mysql_version < '5.5'
|
77
|
+
'show innodb status'
|
78
|
+
else
|
79
|
+
'show engine innodb status'
|
80
|
+
end
|
81
|
+
self.connection.select_value(cmd)
|
82
|
+
DeadlockRetry.innodb_status_cmd = cmd
|
70
83
|
rescue
|
71
|
-
|
84
|
+
logger.info "Cannot log innodb status: #{$!.message}"
|
85
|
+
DeadlockRetry.innodb_status_cmd = false
|
72
86
|
end
|
73
87
|
end
|
74
88
|
|
@@ -80,12 +94,12 @@ module DeadlockRetry
|
|
80
94
|
lines.each_line do |line|
|
81
95
|
logger.warn line
|
82
96
|
end
|
83
|
-
rescue
|
97
|
+
rescue => e
|
84
98
|
# Access denied, ignore
|
85
|
-
logger.
|
99
|
+
logger.info "Cannot log innodb status: #{e.message}"
|
86
100
|
end
|
87
101
|
|
88
102
|
end
|
89
103
|
end
|
90
104
|
|
91
|
-
ActiveRecord::Base.send(:include, DeadlockRetry)
|
105
|
+
ActiveRecord::Base.send(:include, DeadlockRetry) if defined?(ActiveRecord)
|
data/test/deadlock_retry_test.rb
CHANGED
@@ -7,6 +7,7 @@ require 'active_record/version'
|
|
7
7
|
puts "Testing ActiveRecord #{ActiveRecord::VERSION::STRING}"
|
8
8
|
|
9
9
|
require 'test/unit'
|
10
|
+
require 'mocha'
|
10
11
|
require 'logger'
|
11
12
|
require "deadlock_retry"
|
12
13
|
|
@@ -36,8 +37,12 @@ class MockModel
|
|
36
37
|
[]
|
37
38
|
end
|
38
39
|
|
39
|
-
def self.
|
40
|
-
|
40
|
+
def self.execute(sql)
|
41
|
+
[['version', '5.1.45']]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.select_value(sql)
|
45
|
+
true
|
41
46
|
end
|
42
47
|
|
43
48
|
include DeadlockRetry
|
@@ -48,6 +53,7 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
48
53
|
TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
|
49
54
|
|
50
55
|
def setup
|
56
|
+
MockModel.stubs(:exponential_pause)
|
51
57
|
end
|
52
58
|
|
53
59
|
def test_no_errors
|
@@ -83,9 +89,9 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
83
89
|
end
|
84
90
|
|
85
91
|
def test_innodb_status_availability
|
86
|
-
DeadlockRetry.
|
92
|
+
DeadlockRetry.innodb_status_cmd = nil
|
87
93
|
MockModel.transaction {}
|
88
|
-
assert_equal
|
94
|
+
assert_equal "show innodb status", DeadlockRetry.innodb_status_cmd
|
89
95
|
end
|
90
96
|
|
91
97
|
|
metadata
CHANGED
@@ -1,28 +1,35 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: deadlock_retry
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.2
|
4
5
|
prerelease:
|
5
|
-
version: 1.1.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Jamis Buck
|
9
9
|
- Mike Perham
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
date: 2011-10-27 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mocha
|
17
|
+
requirement: &2152103420 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2152103420
|
26
|
+
description: Provides automatic deadlock retry and logging functionality for ActiveRecord
|
27
|
+
and MySQL
|
18
28
|
email: mperham@gmail.com
|
19
29
|
executables: []
|
20
|
-
|
21
30
|
extensions: []
|
22
|
-
|
23
31
|
extra_rdoc_files: []
|
24
|
-
|
25
|
-
files:
|
32
|
+
files:
|
26
33
|
- .gitignore
|
27
34
|
- CHANGELOG
|
28
35
|
- LICENSE
|
@@ -33,30 +40,27 @@ files:
|
|
33
40
|
- test/deadlock_retry_test.rb
|
34
41
|
homepage: http://github.com/mperham/deadlock_retry
|
35
42
|
licenses: []
|
36
|
-
|
37
43
|
post_install_message:
|
38
44
|
rdoc_options: []
|
39
|
-
|
40
|
-
require_paths:
|
45
|
+
require_paths:
|
41
46
|
- lib
|
42
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
48
|
none: false
|
44
|
-
requirements:
|
45
|
-
- -
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version:
|
48
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
54
|
none: false
|
50
|
-
requirements:
|
51
|
-
- -
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version:
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
54
59
|
requirements: []
|
55
|
-
|
56
60
|
rubyforge_project:
|
57
|
-
rubygems_version: 1.
|
61
|
+
rubygems_version: 1.8.10
|
58
62
|
signing_key:
|
59
63
|
specification_version: 3
|
60
|
-
summary: Provides automatic deadlock retry and logging functionality for ActiveRecord
|
64
|
+
summary: Provides automatic deadlock retry and logging functionality for ActiveRecord
|
65
|
+
and MySQL
|
61
66
|
test_files: []
|
62
|
-
|