diff --git a/docker/init-invidious-db.sh b/docker/init-invidious-db.sh index 22b4cc5f..afdc001e 100755 --- a/docker/init-invidious-db.sh +++ b/docker/init-invidious-db.sh @@ -1,6 +1,8 @@ #!/bin/bash set -eou pipefail +psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -c "CREATE SCHEMA IF NOT EXISTS backup" + psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channels.sql psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/videos.sql psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channel_videos.sql diff --git a/src/invidious/database/migrator.cr b/src/invidious/database/migrator.cr index 660c3203..de508346 100644 --- a/src/invidious/database/migrator.cr +++ b/src/invidious/database/migrator.cr @@ -10,10 +10,17 @@ class Invidious::Database::Migrator versions = load_versions ran_migration = false + backed_up = false load_migrations.sort_by(&.version) .each do |migration| next if versions.includes?(migration.version) + if !backed_up + puts "New migration(s) found: creating database backup" + back_up_database + backed_up = true + end + puts "Running migration: #{migration.class.name}" migration.migrate ran_migration = true @@ -46,4 +53,48 @@ class Invidious::Database::Migrator ) SQL end + + private def back_up_database + table_names_request = <<-SQL + SELECT tablename FROM pg_catalog.pg_tables + WHERE schemaname = 'public' + SQL + + table_names = @db.query_all(table_names_request, as: String) + + table_names.try &.each do |name| + copy_table(name) + end + end + + private def copy_table(table_name : String) + puts "Creating a table backup.#{table_name}. Most recent version" + @db.exec <<-SQL + CREATE TABLE IF NOT EXISTS backup.#{table_name} ( + id bigserial PRIMARY KEY + ) + SQL + + puts "Creating a table backup.#{table_name}. Second most recent version" + @db.exec <<-SQL + CREATE TABLE IF NOT EXISTS backup.#{table_name}_second_most_recent ( + id bigserial PRIMARY KEY + ) + SQL + + puts "Populating table backup.#{table_name}. Second most recent version" + @db.exec <<-SQL + SELECT * INTO backup.#{table_name}_second_most_recent + FROM backup.#{table_name} + SQL + + puts "Populating table backup.#{table_name}. Most recent version" + @db.exec <<-SQL + SELECT * INTO backup.#{table_name} + FROM public.#{table_name} + SQL + + puts "Deleting table backup.#{table_name}. Second most recent version" + @db.exec("DROP TABLE backup.#{table_name}_second_most_recent") + end end