Commit ed363ad1 authored by Kerri Miller's avatar Kerri Miller

Merge branch 'infra_6609_move_statistics_update_to_prevent_long_running_transactions' into 'master'

Move updating statistics logic outside of the transaction

See merge request gitlab-org/gitlab!83018
parents 716d2ec9 09422ff6
...@@ -12,14 +12,29 @@ module Vulnerabilities ...@@ -12,14 +12,29 @@ module Vulnerabilities
private private
def update_with_note(vulnerability, params) def update_vulnerability_with(params)
return false unless vulnerability.update(params) @vulnerability.transaction do
yield if block_given?
Vulnerabilities::Statistics::UpdateService.update_for(vulnerability) update_with_note(params)
SystemNoteService.change_vulnerability_state(vulnerability, @user) if vulnerability.state_previously_changed? end
update_statistics
end
def update_with_note(params)
return false unless @vulnerability.update(params)
# The following service call alters the `previous_changes` of the vulnerability object
# therefore, we are sending the cloned object as that information is important for the rest of the logic.
SystemNoteService.change_vulnerability_state(@vulnerability.clone, @user) if @vulnerability.state_previously_changed?
true true
end end
def update_statistics
Vulnerabilities::Statistics::UpdateService.update_for(@vulnerability) if @vulnerability.previous_changes.present?
end
def authorized? def authorized?
can?(@user, :admin_vulnerability, @project) can?(@user, :admin_vulnerability, @project)
end end
......
...@@ -7,10 +7,8 @@ module Vulnerabilities ...@@ -7,10 +7,8 @@ module Vulnerabilities
def execute def execute
raise Gitlab::Access::AccessDeniedError unless authorized? raise Gitlab::Access::AccessDeniedError unless authorized?
@vulnerability.transaction do update_vulnerability_with(state: Vulnerability.states[:confirmed], confirmed_by: @user, confirmed_at: Time.current) do
DestroyDismissalFeedbackService.new(@user, @vulnerability).execute DestroyDismissalFeedbackService.new(@user, @vulnerability).execute
update_with_note(@vulnerability, state: Vulnerability.states[:confirmed], confirmed_by: @user, confirmed_at: Time.current)
end end
@vulnerability @vulnerability
......
...@@ -16,7 +16,7 @@ module Vulnerabilities ...@@ -16,7 +16,7 @@ module Vulnerabilities
def execute def execute
raise Gitlab::Access::AccessDeniedError unless authorized? raise Gitlab::Access::AccessDeniedError unless authorized?
@vulnerability.transaction do update_vulnerability_with(state: Vulnerability.states[:dismissed], dismissed_by: @user, dismissed_at: Time.current) do
if dismiss_findings if dismiss_findings
result = dismiss_vulnerability_findings result = dismiss_vulnerability_findings
...@@ -25,8 +25,6 @@ module Vulnerabilities ...@@ -25,8 +25,6 @@ module Vulnerabilities
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
end end
end end
update_with_note(@vulnerability, state: Vulnerability.states[:dismissed], dismissed_by: @user, dismissed_at: Time.current)
end end
@vulnerability @vulnerability
......
...@@ -7,10 +7,8 @@ module Vulnerabilities ...@@ -7,10 +7,8 @@ module Vulnerabilities
def execute def execute
raise Gitlab::Access::AccessDeniedError unless authorized? raise Gitlab::Access::AccessDeniedError unless authorized?
@vulnerability.transaction do update_vulnerability_with(state: Vulnerability.states[:resolved], resolved_by: @user, resolved_at: Time.current) do
DestroyDismissalFeedbackService.new(@user, @vulnerability).execute DestroyDismissalFeedbackService.new(@user, @vulnerability).execute
update_with_note(@vulnerability, state: Vulnerability.states[:resolved], resolved_by: @user, resolved_at: Time.current)
end end
@vulnerability @vulnerability
......
...@@ -9,10 +9,8 @@ module Vulnerabilities ...@@ -9,10 +9,8 @@ module Vulnerabilities
def execute def execute
raise Gitlab::Access::AccessDeniedError unless authorized? raise Gitlab::Access::AccessDeniedError unless authorized?
@vulnerability.transaction do update_vulnerability_with(state: Vulnerability.states[:detected], **REVERT_PARAMS) do
DestroyDismissalFeedbackService.new(@user, @vulnerability).execute DestroyDismissalFeedbackService.new(@user, @vulnerability).execute
update_with_note(@vulnerability, state: Vulnerability.states[:detected], **REVERT_PARAMS)
end end
@vulnerability @vulnerability
......
...@@ -2,14 +2,31 @@ ...@@ -2,14 +2,31 @@
RSpec.shared_examples 'calls vulnerability statistics utility services in order' do RSpec.shared_examples 'calls vulnerability statistics utility services in order' do
before do before do
vulnerability.clear_changes_information
allow(SystemNoteService).to receive(:change_vulnerability_state) { |vulnerability, *| vulnerability.clear_changes_information }
allow(Vulnerabilities::Statistics::UpdateService).to receive(:update_for) allow(Vulnerabilities::Statistics::UpdateService).to receive(:update_for)
allow(SystemNoteService).to receive(:change_vulnerability_state)
end end
it 'calls the service classes in order' do context 'when updating the vulnerability fails' do
subject before do
allow(vulnerability).to receive(:update).and_return(false)
end
it 'does not call the service classes' do
subject
expect(SystemNoteService).not_to have_received(:change_vulnerability_state).ordered
expect(Vulnerabilities::Statistics::UpdateService).not_to have_received(:update_for).ordered
end
end
context 'when updating the vulnerability succeeds' do
it 'calls the service classes in order' do
subject
expect(Vulnerabilities::Statistics::UpdateService).to have_received(:update_for).ordered expect(SystemNoteService).to have_received(:change_vulnerability_state).ordered
expect(SystemNoteService).to have_received(:change_vulnerability_state).ordered expect(Vulnerabilities::Statistics::UpdateService).to have_received(:update_for).ordered
end
end end
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