Skip to content

Commit

Permalink
Merge pull request #268 from binford2k/add_flock_to_mitigate_r10k_race
Browse files Browse the repository at this point in the history
Lockfile to mitigate r10k race condition.
  • Loading branch information
rnelson0 authored Jan 5, 2017
2 parents b65cc67 + 7b37890 commit 1b8a56e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 8 deletions.
11 changes: 11 additions & 0 deletions spec/acceptance/basic_webhook_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,16 @@ class {'r10k::webhook':
it { expect(r.stdout).to match(%r{^.*success.*$}) }
it { expect(r.exit_code).to eq(0) }
end
# rubocop:disable RSpec/MultipleExpectations
it 'should successfully lock when hammered with multiple requests' do
4.times do
Thread.new do
shell('/usr/bin/curl -d \'{ "ref": "refs/heads/production" }\' -H "Accept: application/json" "http://localhost:8088/payload" -k -q') do |r|
expect(r.stdout).to match(/^.*success.*$/)
expect(r.exit_code).to eq(0)
end
end
end
end
end
end
25 changes: 17 additions & 8 deletions templates/webhook.bin.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require 'open3'

WEBHOOK_CONFIG = '/etc/webhook.yaml'
PIDFILE = '/var/run/webhook/webhook.pid'
LOCKFILE = '/var/run/webhook/webhook.lock'
APP_ROOT = '/var/run/webhook'

if (File.exists?(WEBHOOK_CONFIG))
Expand Down Expand Up @@ -181,15 +182,23 @@ end
end

def run_command(command)
if Open3.respond_to?('capture3')
stdout, stderr, exit_status = Open3.capture3(command)
message = "triggered: #{command}\n#{stdout}\n#{stderr}"
else
message = "forked: #{command}"
Process.detach(fork{ exec "#{command} &"})
exit_status = 0
message = ''
File.open(LOCKFILE, 'w+') do |file|
# r10k has a small race condition which can cause failed deploys if two happen
# more or less simultaneously. To mitigate, we just lock on a file and wait for
# the other one to complete.
file.flock(File::LOCK_EX)

if Open3.respond_to?('capture3')
stdout, stderr, exit_status = Open3.capture3(command)
message = "triggered: #{command}\n#{stdout}\n#{stderr}"
else
message = "forked: #{command}"
Process.detach(fork{ exec "#{command} &"})
exit_status = 0
end
raise "#{stdout}\n#{stderr}" if exit_status != 0
end
raise "#{stdout}\n#{stderr}" if exit_status != 0
message
end

Expand Down

0 comments on commit 1b8a56e

Please sign in to comment.