From 2aa30760f64a0b386bf1ecc205c8be3a69cc71b4 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 11 Jun 2024 19:54:50 -0500 Subject: [PATCH] Check for pending migrations on app startup. Includes index change migration --- src/invidious.cr | 3 +++ src/invidious/database/migration.cr | 9 +++++++++ .../0011_limit_channel_videos_index.cr | 18 ++++++++++++++++++ src/invidious/database/migrator.cr | 16 +++++++++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/invidious/database/migrations/0011_limit_channel_videos_index.cr diff --git a/src/invidious.cr b/src/invidious.cr index e0bd0101..5e16c4a4 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -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) diff --git a/src/invidious/database/migration.cr b/src/invidious/database/migration.cr index 921d8f38..8be3cad7 100644 --- a/src/invidious/database/migration.cr +++ b/src/invidious/database/migration.cr @@ -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 diff --git a/src/invidious/database/migrations/0011_limit_channel_videos_index.cr b/src/invidious/database/migrations/0011_limit_channel_videos_index.cr new file mode 100644 index 00000000..a5959e7c --- /dev/null +++ b/src/invidious/database/migrations/0011_limit_channel_videos_index.cr @@ -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 \ No newline at end of file diff --git a/src/invidious/database/migrator.cr b/src/invidious/database/migrator.cr index 660c3203..33959a4c 100644 --- a/src/invidious/database/migrator.cr +++ b/src/invidious/database/migrator.cr @@ -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)