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:
parent
eeb2855a48
commit
f216c6d60b
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue