discourse/lib/backup_restore/backup_store.rb
marstall 0513865c3c
FEATURE: Delete backups based on time window (#24296)
* FEATURE: core code, tests for feature to allow backups to removed based on a time window

* FEATURE: getting tests working for time-based backup

* FEATURE: getting tests running

* FEATURE: linting
2023-12-13 13:00:27 -05:00

109 lines
2.4 KiB
Ruby

# frozen_string_literal: true
module BackupRestore
# @abstract
class BackupStore
BackupFileExists = Class.new(RuntimeError)
StorageError = Class.new(RuntimeError)
# @return [BackupStore]
def self.create(opts = {})
case opts[:location] || SiteSetting.backup_location
when BackupLocationSiteSetting::LOCAL
require "backup_restore/local_backup_store"
BackupRestore::LocalBackupStore.new(opts)
when BackupLocationSiteSetting::S3
require "backup_restore/s3_backup_store"
BackupRestore::S3BackupStore.new(opts)
end
end
# @return [Array<BackupFile>]
def files
@files ||= unsorted_files.sort_by { |file| -file.last_modified.to_i }
end
# @return [BackupFile]
def latest_file
files.first
end
def reset_cache
@files = nil
Report.clear_cache(:storage_stats)
end
def delete_old
return unless cleanup_allowed?
return if (backup_files = files).size <= SiteSetting.maximum_backups
backup_files[SiteSetting.maximum_backups..-1].each { |file| delete_file(file.filename) }
reset_cache
end
def delete_prior_to_n_days
window = SiteSetting.remove_older_backups.to_i
return unless window && window.is_a?(Numeric) && window > 0
return unless cleanup_allowed?
files.each do |file|
delete_file(file.filename) if file.last_modified < Time.now.ago(window.days)
end
reset_cache
end
def remote?
fail NotImplementedError
end
# @return [BackupFile]
def file(filename, include_download_source: false)
fail NotImplementedError
end
def delete_file(filename)
fail NotImplementedError
end
def download_file(filename, destination, failure_message = nil)
fail NotImplementedError
end
def upload_file(filename, source_path, content_type)
fail NotImplementedError
end
def generate_upload_url(filename)
fail NotImplementedError
end
def stats
{
used_bytes: used_bytes,
free_bytes: free_bytes,
count: files.size,
last_backup_taken_at: latest_file&.last_modified,
}
end
private
# @return [Array<BackupFile>]
def unsorted_files
fail NotImplementedError
end
def cleanup_allowed?
true
end
def used_bytes
files.sum { |file| file.size }
end
def free_bytes
fail NotImplementedError
end
end
end