Skip to content

Commit

Permalink
Merge pull request #1993 from sul-dlss/check-part-size-audit#1742
Browse files Browse the repository at this point in the history
Log when total zip part size is less than the moab size
  • Loading branch information
jmartin-sul authored Nov 3, 2022
2 parents 293cec4 + 840f486 commit 9c4eb15
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 20 deletions.
23 changes: 10 additions & 13 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude`
# on 2022-10-21 20:17:00 UTC using RuboCop version 1.36.0.
# on 2022-10-26 21:57:32 UTC using RuboCop version 1.37.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -14,7 +14,7 @@ Layout/LineLength:
Exclude:
- 'app/models/druid_version_zip.rb'

# Offense count: 32
# Offense count: 27
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
Lint/AmbiguousBlockAssociation:
Exclude:
Expand All @@ -23,7 +23,6 @@ Lint/AmbiguousBlockAssociation:
- 'spec/services/complete_moab_service/shared_examples.rb'
- 'spec/services/complete_moab_service/update_version_after_validation_spec.rb'
- 'spec/services/complete_moab_service/update_version_spec.rb'
- 'spec/services/shared_examples_complete_moab_handler.rb'

# Offense count: 2
Lint/MissingSuper:
Expand All @@ -34,7 +33,7 @@ Lint/MissingSuper:
# Offense count: 23
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 66
Max: 43

# Offense count: 2
# Configuration parameters: CountBlocks, Max.
Expand All @@ -49,25 +48,23 @@ Metrics/ClassLength:
- 'app/controllers/objects_controller.rb'
- 'app/models/druid_version_zip.rb'

# Offense count: 3
# Offense count: 2
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, Max.
Metrics/CyclomaticComplexity:
Exclude:
- 'app/services/complete_moab_service/check_existence.rb'
- 'app/services/complete_moab_service/update_version.rb'
- 'app/services/audit/catalog_to_archive.rb'
- 'app/services/complete_moab_service/update_version_after_validation.rb'

# Offense count: 40
# Offense count: 38
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods.
Metrics/MethodLength:
Max: 33

# Offense count: 3
# Offense count: 2
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, Max.
Metrics/PerceivedComplexity:
Exclude:
- 'app/services/complete_moab_service/check_existence.rb'
- 'app/services/complete_moab_service/update_version.rb'
- 'app/services/audit/catalog_to_archive.rb'
- 'app/services/complete_moab_service/update_version_after_validation.rb'

# Offense count: 3
Expand All @@ -89,7 +86,7 @@ RSpec/InstanceVariable:
Exclude:
- 'spec/models/moab_storage_directory_spec.rb'

# Offense count: 378
# Offense count: 381
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 21
Expand All @@ -116,7 +113,7 @@ RSpec/SubjectDeclaration:
- 'spec/services/reporters/honeybadger_reporter_spec.rb'
- 'spec/services/reporters/logger_reporter_spec.rb'

# Offense count: 17
# Offense count: 18
# Configuration parameters: EnforcedStyle.
# SupportedStyles: slashes, arguments
Rails/FilePath:
Expand Down
4 changes: 4 additions & 0 deletions app/models/audit_results.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class AuditResults
ZIP_PART_NOT_FOUND = :zip_part_not_found
ZIP_PARTS_COUNT_DIFFERS_FROM_ACTUAL = :zip_parts_count_differs_from_actual
ZIP_PARTS_COUNT_INCONSISTENCY = :zip_parts_count_inconsistency
ZIP_PARTS_SIZE_INCONSISTENCY = :zip_parts_size_inconsistency
ZIP_PARTS_NOT_ALL_REPLICATED = :zip_parts_not_all_replicated
ZIP_PARTS_NOT_CREATED = :zip_parts_not_created

Expand Down Expand Up @@ -75,6 +76,9 @@ class AuditResults
'number of zip parts rows (%{actual_count})',
ZIP_PARTS_COUNT_INCONSISTENCY => '%{version} on %{endpoint_name}: ' \
'ZippedMoabVersion has variation in child parts_counts: %{child_parts_counts}',
ZIP_PARTS_SIZE_INCONSISTENCY => '%{version} on %{endpoint_name}: ' \
'Sum of ZippedMoabVersion child part sizes (%{total_part_size}) is less than what is in ' \
'the Moab: %{moab_version_size}',
ZIP_PARTS_NOT_ALL_REPLICATED => '%{version} on %{endpoint_name}: not all ' \
'ZippedMoabVersion parts are replicated yet: %{unreplicated_parts_list}',
ZIP_PARTS_NOT_CREATED => '%{version} on %{endpoint_name}: no zip_parts exist yet for this ZippedMoabVersion'
Expand Down
8 changes: 4 additions & 4 deletions app/models/druid_version_zip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ def zip_split_size
'10g'
end

def moab_version_size
moab_version_files.sum { |f| File.size(f) }
end

private

# Throws an error if any of the files in the moab are not yet readable. For example due to
Expand All @@ -192,10 +196,6 @@ def total_part_size
part_paths.sum { |part_path| File.size(part_path) }
end

def moab_version_size
moab_version_files.sum { |f| File.size(f) }
end

def moab_version_files
raise "Moab version does not exist: #{moab_version_path}" unless File.exist?(moab_version_path)
Dir
Expand Down
6 changes: 6 additions & 0 deletions app/models/preserved_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ def audit_moab_version_replication!
MoabReplicationAuditJob.perform_later(self)
end

def total_size_of_moab_version(version)
return 0 unless complete_moab

DruidVersionZip.new(druid, version, complete_moab.moab_storage_root.storage_location).moab_version_size
end

# Number of PreservedObjects to audit on a daily basis.
def self.daily_check_count
PreservedObject.count / (PreservationPolicy.default_policy.fixity_ttl / (60 * 60 * 24))
Expand Down
6 changes: 5 additions & 1 deletion app/models/zipped_moab_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# ZippedMoabVersion objects should be:
# preserved_object.current_version * number_of_zip_endpoints_for_preservation_policy
#
# @note Does not have size independent of part(s)
# @note Does not have size independent of part(s), see `#total_part_size`
class ZippedMoabVersion < ApplicationRecord
belongs_to :preserved_object, inverse_of: :zipped_moab_versions
belongs_to :zip_endpoint, inverse_of: :zipped_moab_versions
Expand Down Expand Up @@ -37,4 +37,8 @@ def all_parts_replicated?
# has been created and completely written to disk. see DruidVersionZip.
zip_parts.count.positive? && zip_parts.all?(&:ok?)
end

def total_part_size
zip_parts.sum(&:size)
end
end
9 changes: 9 additions & 0 deletions app/services/audit/catalog_to_archive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ def self.check_child_zip_part_attributes(zmv, results)
return false # everything else relies on checking parts, nothing left to do
end

total_part_size = zmv.total_part_size
moab_version_size = zmv.preserved_object.total_size_of_moab_version(zmv.version)
if total_part_size < moab_version_size
results.add_result(
AuditResults::ZIP_PARTS_SIZE_INCONSISTENCY,
base_hash.merge(total_part_size: total_part_size, moab_version_size: moab_version_size)
)
end

child_parts_counts = zmv.child_parts_counts
if child_parts_counts.length > 1
results.add_result(
Expand Down
10 changes: 9 additions & 1 deletion spec/models/druid_version_zip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
after { FileUtils.rm_rf('/tmp/bj') } # cleanup

context 'when zip size is less than the moab size' do
let(:moab_version_size) { dvz.send(:moab_version_size) }
let(:moab_version_size) { dvz.moab_version_size }
let(:total_part_size) { moab_version_size / 2 }

before do
Expand Down Expand Up @@ -266,6 +266,14 @@
end
end

describe '#moab_version_size' do
let(:dvz) { described_class.new(druid, version, 'spec/fixtures/storage_root01/sdr2objects') }

it 'returns the sum of all file sizes in a moab version' do
expect(dvz.moab_version_size).to eq(1_928_387)
end
end

describe '#part_keys' do
let(:druid) { 'dc048cw1328' }

Expand Down
35 changes: 35 additions & 0 deletions spec/models/preserved_object_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,39 @@
expect(described_class.daily_check_count).to eq 11
end
end

describe '#total_size_of_moab_version' do
let(:druid) { 'bz514sm9647' }
let(:preserved_object) { create(:preserved_object, druid: druid, current_version: current_version) }
let(:current_version) { 3 }

context 'when complete moab is nil' do
it 'returns 0' do
expect(preserved_object.total_size_of_moab_version(current_version)).to eq(0)
end
end

context 'when complete moab exists' do
let!(:cm1) { create(:complete_moab, preserved_object: preserved_object, version: current_version, moab_storage_root: msr) } # rubocop:disable RSpec/LetSetup

context 'when moab version path does not exist' do
let(:msr) { create(:moab_storage_root) }

it 'raises a runtime error' do
expect { preserved_object.total_size_of_moab_version(current_version) }.to raise_error(
RuntimeError,
/Moab version does not exist:/
)
end
end

context 'when moab version exists' do
let(:msr) { MoabStorageRoot.find_by!(storage_location: 'spec/fixtures/storage_root01/sdr2objects') }

it 'returns the sum of the file sizes' do
expect(preserved_object.total_size_of_moab_version(current_version)).to eq(37_989)
end
end
end
end
end
25 changes: 25 additions & 0 deletions spec/models/zipped_moab_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@
end
end

describe '#total_part_size' do
context 'there are no parts' do
it 'returns 0' do
expect(zmv.total_part_size).to eq(0)
end
end

context 'there are parts' do
before do
args = attributes_for(:zip_part)
zmv.zip_parts.create!(
[
args.merge(status: 'ok', parts_count: 1, suffix: '.zip', size: 1234),
args.merge(status: 'ok', parts_count: 1, suffix: '.z01', size: 1234),
args.merge(status: 'ok', parts_count: 1, suffix: '.z02', size: 1234)
]
)
end

it 'returns the sum of the part sizes' do
expect(zmv.total_part_size).to eq(3702)
end
end
end

describe '#child_parts_counts' do
context 'there are no parts' do
it 'returns an empty list' do
Expand Down
23 changes: 22 additions & 1 deletion spec/services/audit/catalog_to_archive_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'rails_helper'

RSpec.describe Audit::CatalogToArchive do
let(:zmv) { create(:zipped_moab_version) }
let(:zmv) { create(:zipped_moab_version, preserved_object: create(:preserved_object_fixture, druid: 'bz514sm9647')) }
let(:results) { AuditResults.new(druid: zmv.preserved_object.druid, moab_storage_root: zmv.zip_endpoint, check_name: 'CatalogToArchiveSpec') }
let(:version) { zmv.version }
let(:endpoint_name) { zmv.zip_endpoint.endpoint_name }
Expand Down Expand Up @@ -90,6 +90,27 @@
end
end

context 'when total part size is less than the moab size' do
before do
args = attributes_for(:zip_part)
zmv.zip_parts.create!(
[
args.merge(status: 'ok', parts_count: 3, suffix: '.zip', size: 111),
args.merge(status: 'ok', parts_count: 3, suffix: '.z01', size: 222),
args.merge(status: 'ok', parts_count: 3, suffix: '.z02', size: 333)
]
)
end

it 'logs the discrepancy' do
described_class.check_child_zip_part_attributes(zmv, results)
msg = "#{result_prefix}: Sum of ZippedMoabVersion child part sizes (666) is less than what is in the Moab: 202938"
expect(results.results).to include(
a_hash_including(AuditResults::ZIP_PARTS_SIZE_INCONSISTENCY => msg)
)
end
end

context 'zip parts have been created' do
context 'some parts are unreplicated' do
before do
Expand Down

0 comments on commit 9c4eb15

Please sign in to comment.