app/lib/morph/backup.rb
# typed: strict
# frozen_string_literal: true
module Morph
# Backup and restore to local files
module Backup
extend T::Sig
sig { void }
def self.backup
unless SiteSetting.read_only_mode
Rails.logger.warn "WARNING: The site is NOT in read-only mode. " \
"So, things might get updated during the backup."
end
backup_mysql
backup_sqlite
backup_redis
system "tar cf db/backups/morph_backup.tar db/backups/*.bz2"
FileUtils.rm_f "db/backups/mysql_backup.sql.bz2"
FileUtils.rm_f "db/backups/sqlite_backup.tar.bz2"
FileUtils.rm_f "db/backups/redis_backup.rdb.bz2"
end
sig { void }
def self.restore
system "tar xf db/backups/morph_backup.tar"
restore_mysql
restore_sqlite
restore_redis
FileUtils.rm_f "db/backups/mysql_backup.sql.bz2"
FileUtils.rm_f "db/backups/sqlite_backup.tar.bz2"
FileUtils.rm_f "db/backups/redis_backup.rdb.bz2"
end
sig { void }
def self.backup_mysql
Rails.logger.info "Removing any previous MySQL backup..."
FileUtils.rm_f "db/backups/mysql_backup.sql"
FileUtils.rm_f "db/backups/mysql_backup.sql.bz2"
FileUtils.mkdir_p "db/backups"
Rails.logger.info "Backing up MySQL..."
system "mysqldump #{mysql_auth} #{mysql_database} " \
"> db/backups/mysql_backup.sql"
Rails.logger.info "Compressing MySQL backup..."
system "bzip2 db/backups/mysql_backup.sql"
end
sig { void }
def self.restore_mysql
Rails.logger.info "Uncompressing MySQL backup..."
system "bunzip2 -k db/backups/mysql_backup.sql.bz2"
Rails.logger.info "Restoring from MySQL backup..."
system "mysql #{mysql_auth} #{mysql_database} " \
"< db/backups/mysql_backup.sql"
FileUtils.rm_f "db/backups/mysql_backup.sql"
end
sig { void }
def self.backup_sqlite
Rails.logger.info "Removing any previous SQLite backup..."
FileUtils.rm_f "db/backups/sqlite_backup.tar"
FileUtils.rm_f "db/backups/sqlite_backup.tar.bz2"
Rails.logger.info "Backup up SQLite..."
# TODO: How shall we maintain permissions?
system "tar cf db/backups/sqlite_backup.tar db/scrapers/data"
Rails.logger.info "Compressing SQLite backup..."
system "bzip2 db/backups/sqlite_backup.tar"
end
sig { void }
def self.restore_sqlite
Rails.logger.info "Uncompressing SQLite backup..."
system "bunzip2 -k db/backups/sqlite_backup.tar.bz2"
Rails.logger.info "Restoring from SQLite backup..."
system "tar xf db/backups/sqlite_backup.tar"
FileUtils.rm_f "db/backups/sqlite_backup.tar"
end
sig { void }
def self.backup_redis
Rails.logger.info "Removing any previous Redis backup..."
FileUtils.rm_f "db/backups/redis_backup.rdb"
FileUtils.rm_f "db/backups/redis_backup.rdb.bz2"
Rails.logger.info "Redis taking snapshot..."
redis = Redis.new
redis.save
Rails.logger.info "Backing up Redis..."
system "cp #{redis_directory}/dump.rdb db/backups/redis_backup.rdb"
Rails.logger.info "Compressing Redis backup..."
system "bzip2 db/backups/redis_backup.rdb"
end
sig { void }
def self.restore_redis
Rails.logger.info "Uncompressing Redis backup..."
system "bunzip2 -k db/backups/redis_backup.rdb.bz2"
Rails.logger.info "Restore from Redis backup..."
system "mv db/backups/redis_backup.rdb #{redis_directory}/dump.rdb"
end
sig { returns(String) }
def self.redis_directory
"/var/lib/redis"
end
sig { returns(String) }
def self.mysql_auth
if mysql_username.blank? && mysql_password.blank?
"-u root"
else
"-u #{mysql_username} -p#{mysql_password}"
end
end
sig { returns(T::Hash[String, String]) }
def self.mysql_configuration
Rails.configuration.database_configuration[Rails.env]
end
sig { returns(T.nilable(String)) }
def self.mysql_database
mysql_configuration["database"]
end
sig { returns(T.nilable(String)) }
def self.mysql_username
mysql_configuration["username"]
end
sig { returns(T.nilable(String)) }
def self.mysql_password
mysql_configuration["password"]
end
end
end