2019-05-02 11:37:35 +02:00
|
|
|
class VirusScannerJob < ApplicationJob
|
2021-03-11 14:42:57 +01:00
|
|
|
class FileNotAnalyzedYetError < StandardError
|
|
|
|
end
|
|
|
|
|
2020-07-13 17:48:09 +02:00
|
|
|
queue_as :active_storage_analysis
|
|
|
|
|
2020-09-03 11:00:59 +02:00
|
|
|
# If by the time the job runs the blob has been deleted, ignore the error
|
2020-07-13 14:31:21 +02:00
|
|
|
discard_on ActiveRecord::RecordNotFound
|
2020-09-03 11:00:59 +02:00
|
|
|
# If the file is deleted during the scan, ignore the error
|
|
|
|
discard_on ActiveStorage::FileNotFoundError
|
2021-03-11 14:42:57 +01:00
|
|
|
# If the file is not analyzed yet, retry later (to avoid clobbering metadata)
|
|
|
|
retry_on FileNotAnalyzedYetError, wait: :exponentially_longer, attempts: 10
|
2021-03-11 18:36:25 +01:00
|
|
|
# If for some reason the file appears invalid, retry for a while
|
2021-04-06 14:59:12 +02:00
|
|
|
retry_on(ActiveStorage::IntegrityError, attempts: 5, wait: 5.seconds) do |job, _error|
|
|
|
|
blob = job.arguments.first
|
|
|
|
|
|
|
|
metadata = {
|
|
|
|
virus_scan_result: ActiveStorage::VirusScanner::INTEGRITY_ERROR,
|
|
|
|
scanned_at: Time.zone.now
|
|
|
|
}
|
|
|
|
|
|
|
|
blob.update!(metadata: blob.metadata.merge(metadata))
|
|
|
|
end
|
2021-03-11 18:36:25 +01:00
|
|
|
|
2019-05-02 11:37:35 +02:00
|
|
|
def perform(blob)
|
2021-03-11 14:42:57 +01:00
|
|
|
if !blob.analyzed? then raise FileNotAnalyzedYetError end
|
|
|
|
if blob.virus_scanner.done? then return end
|
|
|
|
|
2019-05-02 11:37:35 +02:00
|
|
|
metadata = extract_metadata_via_virus_scanner(blob)
|
|
|
|
blob.update!(metadata: blob.metadata.merge(metadata))
|
|
|
|
end
|
|
|
|
|
|
|
|
def extract_metadata_via_virus_scanner(blob)
|
|
|
|
ActiveStorage::VirusScanner.new(blob).metadata
|
|
|
|
end
|
|
|
|
end
|