Check for pending migrations on app startup. Includes index change migration

This commit is contained in:
Matthew 2024-06-11 19:54:50 -05:00
parent 1ae14cc224
commit 2aa30760f6
4 changed files with 43 additions and 3 deletions

View File

@ -135,6 +135,9 @@ end
OUTPUT = CONFIG.output.upcase == "STDOUT" ? STDOUT : File.open(CONFIG.output, mode: "a")
LOGGER = Invidious::LogHandler.new(OUTPUT, CONFIG.log_level)
# Check pending migrations
Invidious::Database::Migrator.new(PG_DB).check_pending_migrations
# Check table integrity
Invidious::Database.check_integrity(CONFIG)

View File

@ -4,11 +4,16 @@ abstract class Invidious::Database::Migration
end
@@version : Int64?
@@required : Bool = false
def self.version(version : Int32 | Int64)
@@version = version.to_i64
end
def self.required(required : Bool)
@@required = required
end
getter? completed = false
def initialize(@db : DB::Database)
@ -32,6 +37,10 @@ abstract class Invidious::Database::Migration
@@version.not_nil!
end
def required? : Bool
@@required
end
private def track(conn : DB::Connection)
conn.exec("INSERT INTO #{Migrator::MIGRATIONS_TABLE} (version) VALUES ($1)", version)
end

View File

@ -0,0 +1,18 @@
module Invidious::Database::Migrations
class LimitChannelVideosIndex < Migration
version 11
def up(conn : DB::Connection)
conn.exec <<-SQL
CREATE INDEX IF NOT EXISTS channel_videos_ucid_published_idx
ON public.channel_videos
USING btree
(ucid COLLATE pg_catalog."default", published);
SQL
conn.exec <<-SQL
DROP INDEX IF EXISTS channel_videos_ucid_idx;
SQL
end
end
end

View File

@ -1,5 +1,6 @@
class Invidious::Database::Migrator
MIGRATIONS_TABLE = "public.invidious_migrations"
MIGRATE_INSTRUCTION = "Run `invidious --migrate` to apply the migration(s)."
class_getter migrations = [] of Invidious::Database::Migration.class
@ -22,11 +23,20 @@ class Invidious::Database::Migrator
puts "No migrations to run." unless ran_migration
end
def pending_migrations? : Bool
def check_pending_migrations
versions = load_versions
load_migrations.sort_by(&.version)
.any? { |migration| !versions.includes?(migration.version) }
pending_migrations = load_migrations.sort_by(&.version)
.select { |migration| !versions.includes?(migration.version) }
return if pending_migrations.empty?
if pending_migrations.any?(&.required?)
LOGGER.error("There are pending migrations and the application is unable to continue. #{MIGRATE_INSTRUCTION}")
exit 1
else
LOGGER.warn("There are pending migrations. #{MIGRATE_INSTRUCTION}")
end
end
private def load_migrations : Array(Invidious::Database::Migration)