deadlock_retry 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,6 +1,10 @@
1
1
  deadlock_retry changes
2
2
 
3
- == v1.0.1
3
+ == v1.1.1 (2011-05-13)
4
+
5
+ * Conditionally log INNODB STATUS only if user has permission. (osheroff)
6
+
7
+ == v1.1.0 (2011-04-20)
4
8
 
5
9
  * Modernize.
6
10
  * Drop support for Rails 2.1 and earlier.
@@ -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.0"
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}
@@ -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 = connection.select_value("show innodb status")
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)
@@ -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.7'
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.0
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-04-20 00:00:00 -07:00
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.6.2
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