Commit d3205996 authored by Adam Cohen's avatar Adam Cohen Committed by Stan Hu

Remove subtransaction from HistoricalStatistics

parent 7588f89b
......@@ -3,7 +3,40 @@
module Vulnerabilities
module HistoricalStatistics
class UpdateService
VULNERABILITY_STATISTIC_ATTRIBUTES = %w(total critical high medium low unknown info letter_grade).freeze
UPSERT_SQL = <<~SQL
INSERT INTO vulnerability_historical_statistics
(project_id, total, info, unknown, low, medium, high, critical, letter_grade, date, created_at, updated_at)
(%{stats_sql})
ON CONFLICT (project_id, date)
DO UPDATE SET
total = EXCLUDED.total,
info = EXCLUDED.info,
unknown = EXCLUDED.unknown,
low = EXCLUDED.low,
medium = EXCLUDED.medium,
high = EXCLUDED.high,
critical = EXCLUDED.critical,
letter_grade = EXCLUDED.letter_grade,
updated_at = EXCLUDED.updated_at
SQL
STATS_SQL = <<~SQL
SELECT
project_id,
total,
info,
unknown,
low,
medium,
high,
critical,
letter_grade,
updated_at AS date,
now() AS created_at,
now() AS updated_at
FROM vulnerability_statistics
WHERE project_id = %{project_id}
SQL
def self.update_for(project)
new(project).execute
......@@ -13,22 +46,17 @@ module Vulnerabilities
@project = project
end
# rubocop: disable CodeReuse/ActiveRecord
def execute
return unless update_statistic?
::Vulnerabilities::HistoricalStatistic.safe_ensure_unique(retries: 1) do
historical_statistic = vulnerability_historical_statistics.find_or_initialize_by(date: vulnerability_statistic.updated_at)
historical_statistic.update(vulnerability_statistic.attributes.slice(*VULNERABILITY_STATISTIC_ATTRIBUTES))
end
ApplicationRecord.connection.execute(upsert_sql)
end
# rubocop: enable CodeReuse/ActiveRecord
private
attr_reader :project
delegate :vulnerability_statistic, :vulnerability_historical_statistics, to: :project
delegate :vulnerability_statistic, to: :project
def update_statistic?
keep_statistics_always_consistent? && vulnerability_statistic.present?
......@@ -37,6 +65,14 @@ module Vulnerabilities
def keep_statistics_always_consistent?
Feature.enabled?(:keep_historical_vulnerability_statistics_always_consistent, project)
end
def upsert_sql
UPSERT_SQL % { stats_sql: stats_sql }
end
def stats_sql
STATS_SQL % { project_id: project.id }
end
end
end
end
......@@ -48,6 +48,12 @@ RSpec.describe Vulnerabilities::HistoricalStatistics::UpdateService do
expect { update_stats }.to change { Vulnerabilities::HistoricalStatistic.count }.by(1)
end
end
it 'changes the updated_at timestamp of the existing historical statistic entity' do
historical_statistic = create(:vulnerability_historical_statistic, project: project, letter_grade: 'c')
expect { update_stats }.to change { historical_statistic.reload.updated_at }
end
end
context 'when the statistic is empty' do
......
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