FEATURE: Drop "backup" schema 7 days after restore

The "backup" schema is used to rollback a failed restore. It isn't useful after a longer period of time and turns into a waste of disk space.
This commit is contained in:
Gerhard Schlager 2020-01-15 23:19:13 +01:00
parent eeb2855a48
commit f216c6d60b
4 changed files with 102 additions and 0 deletions

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Jobs
class DropBackupSchema < ::Jobs::Scheduled
every 1.day
def execute(_)
BackupRestore::DatabaseRestorer.drop_backup_schema
end
end
end

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class BackupMetadata < ActiveRecord::Base class BackupMetadata < ActiveRecord::Base
LAST_RESTORE_DATE = "last_restore_date"
def self.value_for(name) def self.value_for(name)
where(name: name).pluck_first(:value).presence where(name: name).pluck_first(:value).presence
end end

View File

@ -8,6 +8,7 @@ module BackupRestore
MAIN_SCHEMA = "public" MAIN_SCHEMA = "public"
BACKUP_SCHEMA = "backup" BACKUP_SCHEMA = "backup"
DROP_BACKUP_SCHEMA_AFTER_DAYS = 7
def initialize(logger, current_db) def initialize(logger, current_db)
@logger = logger @logger = logger
@ -25,6 +26,8 @@ module BackupRestore
restore_dump restore_dump
migrate_database migrate_database
reconnect_database reconnect_database
self.class.update_last_restore_date
end end
def rollback def rollback
@ -42,6 +45,20 @@ module BackupRestore
drop_created_discourse_functions drop_created_discourse_functions
end end
def self.drop_backup_schema
if backup_schema_dropable?
ActiveRecord::Base.connection.drop_schema(BACKUP_SCHEMA)
end
end
def self.update_last_restore_date
BackupMetadata.where(name: BackupMetadata::LAST_RESTORE_DATE).delete_all
BackupMetadata.create!(
name: BackupMetadata::LAST_RESTORE_DATE,
value: Time.zone.now.iso8601
)
end
protected protected
def restore_dump def restore_dump
@ -178,5 +195,20 @@ module BackupRestore
rescue => ex rescue => ex
log "Something went wrong while dropping functions from the discourse_functions schema", ex log "Something went wrong while dropping functions from the discourse_functions schema", ex
end end
def self.backup_schema_dropable?
return false unless ActiveRecord::Base.connection.schema_exists?(BACKUP_SCHEMA)
last_restore_date = BackupMetadata.value_for(BackupMetadata::LAST_RESTORE_DATE)
if last_restore_date.present?
last_restore_date = Time.zone.parse(last_restore_date)
return last_restore_date + DROP_BACKUP_SCHEMA_AFTER_DAYS.days < Time.zone.now
end
update_last_restore_date
false
end
private_class_method :backup_schema_dropable?
end end
end end

View File

@ -67,6 +67,14 @@ describe BackupRestore::DatabaseRestorer do
subject.restore("foo.sql") subject.restore("foo.sql")
end end
it "stores the date of the last restore" do
date_string = "2020-01-10T17:38:27Z"
freeze_time(Time.parse(date_string))
execute_stubbed_restore
expect(BackupMetadata.value_for(BackupMetadata::LAST_RESTORE_DATE)).to eq(date_string)
end
context "with real psql" do context "with real psql" do
after do after do
psql = BackupRestore::DatabaseRestorer.psql_command psql = BackupRestore::DatabaseRestorer.psql_command
@ -176,4 +184,53 @@ describe BackupRestore::DatabaseRestorer do
subject.clean_up subject.clean_up
end end
end end
describe ".drop_backup_schema" do
subject { BackupRestore::DatabaseRestorer }
context "when no backup schema exists" do
it "doesn't do anything" do
ActiveRecord::Base.connection.expects(:schema_exists?).with("backup").returns(false)
ActiveRecord::Base.connection.expects(:drop_schema).never
subject.drop_backup_schema
end
end
context "when a backup schema exists" do
before do
ActiveRecord::Base.connection.expects(:schema_exists?).with("backup").returns(true)
end
it "drops the schema when the last restore was long ago" do
ActiveRecord::Base.connection.expects(:drop_schema).with("backup")
freeze_time(8.days.ago) do
subject.update_last_restore_date
end
subject.drop_backup_schema
end
it "doesn't drop the schema when the last restore was recently" do
ActiveRecord::Base.connection.expects(:drop_schema).with("backup").never
freeze_time(6.days.ago) do
subject.update_last_restore_date
end
subject.drop_backup_schema
end
it "stores the current date when there is no record of the last restore" do
ActiveRecord::Base.connection.expects(:drop_schema).with("backup").never
date_string = "2020-01-08T17:38:27Z"
freeze_time(Time.parse(date_string))
subject.drop_backup_schema
expect(BackupMetadata.value_for(BackupMetadata::LAST_RESTORE_DATE)).to eq(date_string)
end
end
end
end end