Skip to content
This repository is currently being migrated. It's locked while the migration is in progress.

Commit f7b8978

Browse files
authored
VEBT-5053/archiving benchmark (#1613)
* fix csv * bump devise * devise change * add logging to archive process * add start finish * add clear at end to clear variable * bump bcrypt
1 parent 8233d8e commit f7b8978

3 files changed

Lines changed: 59 additions & 7 deletions

File tree

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ gem 'active_model_serializers', '~> 0.10.15' # JSON API
88
gem 'activerecord-import' # Mass importing of CSV data
99
gem 'activerecord-session_store' # Switch to AR session storage in case of failure pushing to GIBCT
1010
gem 'base64', '~> 0.2.0' # ruby 3.4.0 warning said to add
11-
gem 'bcrypt', '~> 3.1.20'
11+
gem 'bcrypt', '>= 3.1.22'
1212
gem 'bootsnap', require: false
1313
gem 'cancancan', '~> 3.6' # Use cancancan for authorization
1414
gem 'cgi', '>= 0.4.2'

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ GEM
103103
ice_nine (~> 0.11.0)
104104
thread_safe (~> 0.3, >= 0.3.1)
105105
base64 (0.2.0)
106-
bcrypt (3.1.20)
106+
bcrypt (3.1.22)
107107
benchmark (0.4.0)
108108
better_errors (2.10.1)
109109
erubi (>= 1.0.0)
@@ -602,7 +602,7 @@ DEPENDENCIES
602602
activerecord-import
603603
activerecord-session_store
604604
base64 (~> 0.2.0)
605-
bcrypt (~> 3.1.20)
605+
bcrypt (>= 3.1.22)
606606
better_errors
607607
binding_of_caller
608608
bootsnap

app/models/archiver.rb

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
# TODO: refactor line #6 when we write new ratings code
4-
module Archiver
4+
module Archiver # rubocop:disable Metrics/ModuleLength
55
ARCHIVE_TYPES = [
66
{ source: InstitutionRating, archive: InstitutionRatingsArchive },
77
{ source: InstitutionProgram, archive: InstitutionProgramsArchive },
@@ -13,13 +13,55 @@ module Archiver
1313
{ source: CalculatorConstantVersion, archive: CalculatorConstantVersionsArchive }
1414
].freeze
1515

16-
def self.archive_previous_versions
16+
def self.metrics
17+
@metrics ||= {}
18+
end
19+
20+
def self.benchmark_start(metric_name)
21+
metrics[metric_name] ||= {}
22+
metrics[metric_name]['start'] = Time.now.utc
23+
end
24+
25+
def self.benchmark_end(metric_name, count = nil)
26+
metrics[metric_name] ||= {}
27+
metric = metrics[metric_name]
28+
metric['finish'] = Time.now.utc
29+
metric['duration'] = metric['finish'] - metric['start']
30+
if count
31+
metric['records'] = count
32+
metric['avg_per_record'] = metric['duration'] / metric['records'] unless count.zero?
33+
end
34+
end
35+
36+
def self.print_metrics_report
37+
total = metrics.delete('archive_total')['duration']
38+
report = metrics.map do |name, values|
39+
<<~HERE
40+
+ #{name}:
41+
- start: #{values['start']}
42+
- end: #{values['finish']}
43+
- duration: #{values['duration']}
44+
- records: #{values['records']}
45+
- avg_per_record: #{values.fetch('avg_per_record', 'N/A')}
46+
HERE
47+
end.join("\n")
48+
Rails.logger.info(<<~HERE)
49+
========== ARCHIVE BENCHMARKS ==========
50+
+ Total Archive Time: #{total}
51+
52+
#{report}
53+
HERE
54+
metrics.clear
55+
end
56+
57+
def self.archive_previous_versions # rubocop:disable Metrics/AbcSize
1758
# don't bother if nothing to archive. Also note that during the initial buildout, there is no previous version
1859
# The below previous_version will exception out and cause all the work to be rolled back.
1960
return unless Version.current_production && Version.previous_production
2061

2162
production_version = Version.current_production.number
2263

64+
benchmark_start('archive_total')
2365
Rails.logger.info "\n\n\n*** Starting Archive process"
2466
Rails.logger.info 'Getting default timeout parameter'
2567
get_timeout_parameter
@@ -37,8 +79,12 @@ def self.archive_previous_versions
3779
else
3880
archivable[:source].joins(:version)
3981
end
40-
41-
source.where('number < ?', production_version).in_batches.delete_all
82+
source.where('number < ?', production_version).tap do |records|
83+
count = records.count
84+
benchmark_start("delete_#{source.table_name}")
85+
records.in_batches.delete_all
86+
benchmark_end("delete_#{source.table_name}", count)
87+
end
4288
end
4389
end
4490
rescue ActiveRecord::StatementInvalid => e
@@ -49,9 +95,11 @@ def self.archive_previous_versions
4995
process_exception(notice, e, production_version)
5096
end
5197

98+
benchmark_end('archive_total')
5299
Rails.logger.info 'Done archiving, getting default timeout parameter'
53100
get_timeout_parameter
54101
Rails.logger.info "*** End of Archiving process\n\n\n"
102+
print_metrics_report
55103
end
56104

57105
def self.create_archives(source, archive, production_version)
@@ -65,12 +113,16 @@ def self.create_archives(source, archive, production_version)
65113
Rails.logger.info "query as sql: #{base_query.to_sql}"
66114
archive_columns = archive.column_names
67115

116+
benchmark_start("create_#{archive.table_name}")
117+
orig_count = archive.count
68118
base_query.find_in_batches(batch_size: 1000) do |records|
69119
attributes = records.map { |record| record.attributes.slice(*archive_columns) }
70120
# rubocop:disable Rails/SkipsModelValidations
71121
archive.insert_all(attributes) if attributes.present?
72122
# rubocop:enable Rails/SkipsModelValidations
73123
end
124+
125+
benchmark_end("create_#{archive.table_name}", archive.count - orig_count)
74126
Rails.logger.info "*** Done archiving #{source.table_name}"
75127
end
76128

0 commit comments

Comments
 (0)