Last active
August 29, 2015 13:57
-
-
Save tommeier/9360840 to your computer and use it in GitHub Desktop.
Deadlock specs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe 'deadlocks' do | |
describe "on login" do | |
it 'should allow multiple requests to login at same time' do | |
# Check original is ok | |
::Customer.find_by(id: customer_id).should be_blank | |
forks = [] | |
1.upto(4).each do |index| | |
forks << fork_with_new_connection do | |
# Trigger any code that deadlocks like login | |
end | |
end | |
forks.each do |pid| | |
_, fork_status = Process.waitpid2(pid) | |
# Fork should not have raised an error (as a result of deadlock) | |
fork_status.exitstatus.should eq(0) | |
end | |
# Check customer is created even with deadlocks | |
customer = ::Customer.find_by(id: customer_id) | |
customer.should be_present | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sub forks within specs must wrap the connection to ensure cleanup occurs correctly | |
def fork_with_new_connection | |
ActiveRecord::Base.remove_connection | |
fork_pid = fork do | |
# Ensure coverage is unique to forked process | |
SimpleCov.command_name("forked-#{Process.pid}-#{SimpleCov.command_name}") | |
#Skip full format, but merge coverage results before final | |
# .format! is called in outer process | |
SimpleCov.at_exit { SimpleCov.result } | |
begin | |
ActiveRecord::Base.establish_connection | |
DatabaseCleaner.start unless it_should_truncate_data?(example.metadata) | |
yield | |
ensure | |
DatabaseCleaner.clean unless it_should_truncate_data?(example.metadata) | |
ActiveRecord::Base.remove_connection | |
end | |
end | |
ActiveRecord::Base.establish_connection | |
fork_pid | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SimpleCov.at_exit do | |
# Ensure multiple processes or forks lock coverage file during result merging | |
# (and ensure one process result isn't clobbered) | |
SimpleCov.with_lock { SimpleCov.result.format! } | |
end | |
SimpleCov.class_eval do | |
# Run any command with a lockfile | |
# Useful for when generating coverage across forks/threads | |
def self.with_lock | |
parallel_lock = File.join(self.coverage_path, '.lockfile') | |
File.open(parallel_lock, "w+") do |f| | |
f.flock(File::LOCK_EX) | |
yield | |
end | |
end | |
# Allow a specific command name for a block of code executing | |
# and run simple merge of results without full coverage generated | |
def self.with_command_name(new_command_name) | |
original_command_name = command_name | |
command_name(new_command_name) | |
yield | |
with_lock do | |
self.result #Merge results without full report | |
end | |
command_name(original_command_name) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment