95 lines
2.3 KiB
Ruby
95 lines
2.3 KiB
Ruby
begin
|
|
require 'active_record'
|
|
rescue LoadError
|
|
if ENV['ACTIVERECORD_PATH'].nil?
|
|
abort <<MSG
|
|
Please set the ACTIVERECORD_PATH environment variable to the directory
|
|
containing the active_record.rb file.
|
|
MSG
|
|
else
|
|
$LOAD_PATH.unshift << ENV['ACTIVERECORD_PATH']
|
|
begin
|
|
require 'active_record'
|
|
rescue LoadError
|
|
abort "ActiveRecord could not be found."
|
|
end
|
|
end
|
|
end
|
|
|
|
require 'test/unit'
|
|
require "#{File.dirname(__FILE__)}/../lib/deadlock_retry"
|
|
|
|
class MockModel
|
|
@@open_transactions = 0
|
|
|
|
def self.transaction(*objects)
|
|
@@open_transactions += 1
|
|
yield
|
|
ensure
|
|
@@open_transactions -= 1
|
|
end
|
|
|
|
def self.open_transactions
|
|
@@open_transactions
|
|
end
|
|
|
|
def self.connection
|
|
self
|
|
end
|
|
|
|
def self.logger
|
|
@logger ||= Logger.new(nil)
|
|
end
|
|
|
|
include DeadlockRetry
|
|
end
|
|
|
|
class DeadlockRetryTest < Test::Unit::TestCase
|
|
DEADLOCK_ERROR = "MySQL::Error: Deadlock found when trying to get lock"
|
|
TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
|
|
|
|
def test_no_errors
|
|
assert_equal :success, MockModel.transaction { :success }
|
|
end
|
|
|
|
def test_no_errors_with_deadlock
|
|
errors = [ DEADLOCK_ERROR ] * 3
|
|
assert_equal :success, MockModel.transaction { raise ActiveRecord::StatementInvalid, errors.shift unless errors.empty?; :success }
|
|
assert errors.empty?
|
|
end
|
|
|
|
def test_no_errors_with_lock_timeout
|
|
errors = [ TIMEOUT_ERROR ] * 3
|
|
assert_equal :success, MockModel.transaction { raise ActiveRecord::StatementInvalid, errors.shift unless errors.empty?; :success }
|
|
assert errors.empty?
|
|
end
|
|
|
|
def test_error_if_limit_exceeded
|
|
assert_raise(ActiveRecord::StatementInvalid) do
|
|
MockModel.transaction { raise ActiveRecord::StatementInvalid, DEADLOCK_ERROR }
|
|
end
|
|
end
|
|
|
|
def test_error_if_unrecognized_error
|
|
assert_raise(ActiveRecord::StatementInvalid) do
|
|
MockModel.transaction { raise ActiveRecord::StatementInvalid, "Something else" }
|
|
end
|
|
end
|
|
|
|
def test_error_in_nested_transaction_should_retry_outermost_transaction
|
|
tries = 0
|
|
errors = 0
|
|
|
|
MockModel.transaction do
|
|
tries += 1
|
|
MockModel.transaction do
|
|
MockModel.transaction do
|
|
errors += 1
|
|
raise ActiveRecord::StatementInvalid, "MySQL::Error: Lock wait timeout exceeded" unless errors > 3
|
|
end
|
|
end
|
|
end
|
|
|
|
assert_equal 4, tries
|
|
end
|
|
end
|