deadlock_retry 1.1.0 → 1.1.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.
- data/CHANGELOG +5 -1
- data/deadlock_retry.gemspec +1 -1
- data/lib/deadlock_retry.rb +33 -4
- data/test/deadlock_retry_test.rb +20 -2
- metadata +3 -5
data/CHANGELOG
CHANGED
data/deadlock_retry.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{deadlock_retry}
|
5
|
-
s.version = "1.1.
|
5
|
+
s.version = "1.1.1"
|
6
6
|
s.authors = ["Jamis Buck", "Mike Perham"]
|
7
7
|
s.description = s.summary = %q{Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL}
|
8
8
|
s.email = %q{mperham@gmail.com}
|
data/lib/deadlock_retry.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module DeadlockRetry
|
2
|
-
|
3
2
|
def self.included(base)
|
4
3
|
base.extend(ClassMethods)
|
5
4
|
base.class_eval do
|
@@ -9,6 +8,16 @@ module DeadlockRetry
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
11
|
+
@@innodb_status_available = nil
|
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
|
20
|
+
|
12
21
|
module ClassMethods
|
13
22
|
DEADLOCK_ERROR_MESSAGES = [
|
14
23
|
"Deadlock found when trying to get lock",
|
@@ -17,9 +26,12 @@ module DeadlockRetry
|
|
17
26
|
|
18
27
|
MAXIMUM_RETRIES_ON_DEADLOCK = 3
|
19
28
|
|
29
|
+
|
20
30
|
def transaction_with_deadlock_handling(*objects, &block)
|
21
31
|
retry_count = 0
|
22
32
|
|
33
|
+
check_innodb_status_available
|
34
|
+
|
23
35
|
begin
|
24
36
|
transaction_without_deadlock_handling(*objects, &block)
|
25
37
|
rescue ActiveRecord::StatementInvalid => error
|
@@ -28,7 +40,7 @@ module DeadlockRetry
|
|
28
40
|
raise if retry_count >= MAXIMUM_RETRIES_ON_DEADLOCK
|
29
41
|
retry_count += 1
|
30
42
|
logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
|
31
|
-
log_innodb_status
|
43
|
+
log_innodb_status if DeadlockRetry.innodb_status_available?
|
32
44
|
retry
|
33
45
|
else
|
34
46
|
raise
|
@@ -43,10 +55,27 @@ module DeadlockRetry
|
|
43
55
|
connection.open_transactions != 0
|
44
56
|
end
|
45
57
|
|
58
|
+
def show_innodb_status
|
59
|
+
self.connection.select_value("show innodb status")
|
60
|
+
end
|
61
|
+
|
62
|
+
# Should we try to log innodb status -- if we don't have permission to,
|
63
|
+
# we actually break in-flight transactions, silently (!)
|
64
|
+
def check_innodb_status_available
|
65
|
+
return unless DeadlockRetry.innodb_status_available? == nil
|
66
|
+
|
67
|
+
begin
|
68
|
+
show_innodb_status
|
69
|
+
DeadlockRetry.innodb_status_available = true
|
70
|
+
rescue
|
71
|
+
DeadlockRetry.innodb_status_available = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
46
75
|
def log_innodb_status
|
47
76
|
# show innodb status is the only way to get visiblity into why
|
48
77
|
# the transaction deadlocked. log it.
|
49
|
-
lines =
|
78
|
+
lines = show_innodb_status
|
50
79
|
logger.warn "INNODB Status follows:"
|
51
80
|
lines.each_line do |line|
|
52
81
|
logger.warn line
|
@@ -59,4 +88,4 @@ module DeadlockRetry
|
|
59
88
|
end
|
60
89
|
end
|
61
90
|
|
62
|
-
ActiveRecord::Base.send(:include, DeadlockRetry)
|
91
|
+
ActiveRecord::Base.send(:include, DeadlockRetry)
|
data/test/deadlock_retry_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
# Change the version if you want to test a different version of ActiveRecord
|
4
|
-
gem 'activerecord', '3.0
|
4
|
+
gem 'activerecord', ' ~>3.0'
|
5
5
|
require 'active_record'
|
6
6
|
require 'active_record/version'
|
7
7
|
puts "Testing ActiveRecord #{ActiveRecord::VERSION::STRING}"
|
@@ -32,6 +32,14 @@ class MockModel
|
|
32
32
|
@logger ||= Logger.new(nil)
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.show_innodb_status
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.reset_innodb_status_availability
|
40
|
+
DeadlockRetry.innodb_status_availability = nil
|
41
|
+
end
|
42
|
+
|
35
43
|
include DeadlockRetry
|
36
44
|
end
|
37
45
|
|
@@ -39,6 +47,9 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
39
47
|
DEADLOCK_ERROR = "MySQL::Error: Deadlock found when trying to get lock"
|
40
48
|
TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
|
41
49
|
|
50
|
+
def setup
|
51
|
+
end
|
52
|
+
|
42
53
|
def test_no_errors
|
43
54
|
assert_equal :success, MockModel.transaction { :success }
|
44
55
|
end
|
@@ -71,6 +82,13 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
71
82
|
assert ActiveRecord::Base.respond_to?(:transaction_with_deadlock_handling)
|
72
83
|
end
|
73
84
|
|
85
|
+
def test_innodb_status_availability
|
86
|
+
DeadlockRetry.innodb_status_available = nil
|
87
|
+
MockModel.transaction {}
|
88
|
+
assert_equal true, DeadlockRetry.innodb_status_available?
|
89
|
+
end
|
90
|
+
|
91
|
+
|
74
92
|
def test_error_in_nested_transaction_should_retry_outermost_transaction
|
75
93
|
tries = 0
|
76
94
|
errors = 0
|
@@ -84,7 +102,7 @@ class DeadlockRetryTest < Test::Unit::TestCase
|
|
84
102
|
end
|
85
103
|
end
|
86
104
|
end
|
87
|
-
|
105
|
+
|
88
106
|
assert_equal 4, tries
|
89
107
|
end
|
90
108
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: deadlock_retry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.1.
|
5
|
+
version: 1.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jamis Buck
|
@@ -11,8 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
15
|
-
default_executable:
|
14
|
+
date: 2011-05-14 00:00:00 Z
|
16
15
|
dependencies: []
|
17
16
|
|
18
17
|
description: Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL
|
@@ -32,7 +31,6 @@ files:
|
|
32
31
|
- deadlock_retry.gemspec
|
33
32
|
- lib/deadlock_retry.rb
|
34
33
|
- test/deadlock_retry_test.rb
|
35
|
-
has_rdoc: true
|
36
34
|
homepage: http://github.com/mperham/deadlock_retry
|
37
35
|
licenses: []
|
38
36
|
|
@@ -56,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
54
|
requirements: []
|
57
55
|
|
58
56
|
rubyforge_project:
|
59
|
-
rubygems_version: 1.
|
57
|
+
rubygems_version: 1.7.2
|
60
58
|
signing_key:
|
61
59
|
specification_version: 3
|
62
60
|
summary: Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL
|