Skip to content
Browse files

Add exponential backoff, as suggested by MenTaLguY

  • Loading branch information...
1 parent f02d513 commit 0702856e1e113ffe6e9dc42f654f052ce6762c02 @mperham committed Jul 11, 2011
Showing with 18 additions and 1 deletion.
  1. +4 −0 CHANGELOG
  2. +2 −1 deadlock_retry.gemspec
  3. +10 −0 lib/deadlock_retry.rb
  4. +2 −0 test/deadlock_retry_test.rb
View
4 CHANGELOG
@@ -1,5 +1,9 @@
deadlock_retry changes
+== HEAD
+
+* Exponential backoff, sleep 0, 1, 2, 4... seconds between retries.
+
== v1.1.1 (2011-05-13)
* Conditionally log INNODB STATUS only if user has permission. (osheroff)
View
3 deadlock_retry.gemspec
@@ -2,11 +2,12 @@
Gem::Specification.new do |s|
s.name = %q{deadlock_retry}
- s.version = "1.1.1"
+ s.version = "1.1.2"
s.authors = ["Jamis Buck", "Mike Perham"]
s.description = s.summary = %q{Provides automatic deadlock retry and logging functionality for ActiveRecord and MySQL}
s.email = %q{mperham@gmail.com}
s.files = `git ls-files`.split("\n")
s.homepage = %q{http://github.com/mperham/deadlock_retry}
s.require_paths = ["lib"]
+ s.add_development_dependency 'mocha'
end
View
10 lib/deadlock_retry.rb
@@ -41,6 +41,7 @@ def transaction_with_deadlock_handling(*objects, &block)
retry_count += 1
logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
log_innodb_status if DeadlockRetry.innodb_status_available?
+ exponential_pause(retry_count)
retry
else
raise
@@ -50,6 +51,15 @@ def transaction_with_deadlock_handling(*objects, &block)
private
+ WAIT_TIMES = [0, 1, 2, 4, 8, 16, 32]
+
+ def exponential_pause(count)
+ sec = WAIT_TIMES[count-1] || 32
+ # sleep 0, 1, 2, 4, ... seconds up to the MAXIMUM_RETRIES.
+ # Cap the pause time at 32 seconds.
+ sleep(sec) if sec != 0
+ end
+
def in_nested_transaction?
# open_transactions was added in 2.2's connection pooling changes.
connection.open_transactions != 0
View
2 test/deadlock_retry_test.rb
@@ -7,6 +7,7 @@
puts "Testing ActiveRecord #{ActiveRecord::VERSION::STRING}"
require 'test/unit'
+require 'mocha'
require 'logger'
require "deadlock_retry"
@@ -48,6 +49,7 @@ class DeadlockRetryTest < Test::Unit::TestCase
TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
def setup
+ MockModel.stubs(:exponential_pause)
end
def test_no_errors

0 comments on commit 0702856

Please sign in to comment.
Something went wrong with that request. Please try again.