Commit a88461c6 authored by Shinya Maeda's avatar Shinya Maeda

Fix Forward Deployment Worker causes deadlock

This commit fixes that the Forward Deployment Worker
causes deadlock between ci_builds and deployments table
by the concurrent updates.
parent 02c54ee4
......@@ -323,7 +323,7 @@ module Ci
end
end
before_transition any => [:failed] do |build|
after_transition any => [:failed] do |build|
next unless build.project
next unless build.deployment
......
---
title: Fix Forward Deployment Worker causes deadlock
merge_request: 58861
author:
type: fixed
......@@ -1135,6 +1135,8 @@ RSpec.describe Ci::Build do
end
describe 'state transition as a deployable' do
subject { build.send(event) }
let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) }
let(:deployment) { build.deployment }
let(:environment) { deployment.environment }
......@@ -1149,54 +1151,78 @@ RSpec.describe Ci::Build do
expect(environment.name).to eq('review/master')
end
context 'when transits to running' do
before do
build.run!
shared_examples_for 'avoid deadlock' do
it 'executes UPDATE in the right order' do
recorded = ActiveRecord::QueryRecorder.new { subject }
index_for_build = recorded.log.index { |l| l.include?("UPDATE \"ci_builds\"") }
index_for_deployment = recorded.log.index { |l| l.include?("UPDATE \"deployments\"") }
expect(index_for_build).to be < index_for_deployment
end
end
context 'when transits to running' do
let(:event) { :run! }
it_behaves_like 'avoid deadlock'
it 'transits deployment status to running' do
subject
expect(deployment).to be_running
end
end
context 'when transits to success' do
let(:event) { :success! }
before do
allow(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
build.success!
end
it_behaves_like 'avoid deadlock'
it 'transits deployment status to success' do
subject
expect(deployment).to be_success
end
end
context 'when transits to failed' do
before do
build.drop!
end
let(:event) { :drop! }
it_behaves_like 'avoid deadlock'
it 'transits deployment status to failed' do
subject
expect(deployment).to be_failed
end
end
context 'when transits to skipped' do
before do
build.skip!
end
let(:event) { :skip! }
it_behaves_like 'avoid deadlock'
it 'transits deployment status to skipped' do
subject
expect(deployment).to be_skipped
end
end
context 'when transits to canceled' do
before do
build.cancel!
end
let(:event) { :cancel! }
it_behaves_like 'avoid deadlock'
it 'transits deployment status to canceled' do
subject
expect(deployment).to be_canceled
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment