deadlock_retry 1.1.1 → 1.1.2
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 -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
|
-
|