mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-10-31 04:32:02 +00:00 
			
		
		
		
	Migrations tweaks
This commit is contained in:
		| @@ -27,6 +27,7 @@ require "compress/zip" | ||||
| require "protodec/utils" | ||||
|  | ||||
| require "./invidious/database/*" | ||||
| require "./invidious/database/migrations/*" | ||||
| require "./invidious/helpers/*" | ||||
| require "./invidious/yt_backend/*" | ||||
| require "./invidious/*" | ||||
| @@ -34,7 +35,6 @@ require "./invidious/channels/*" | ||||
| require "./invidious/user/*" | ||||
| require "./invidious/routes/**" | ||||
| require "./invidious/jobs/**" | ||||
| require "./invidious/migrations/*" | ||||
|  | ||||
| CONFIG   = Config.load | ||||
| HMAC_KEY = CONFIG.hmac_key || Random::Secure.hex(32) | ||||
| @@ -113,7 +113,7 @@ OUTPUT = CONFIG.output.upcase == "STDOUT" ? STDOUT : File.open(CONFIG.output, mo | ||||
| LOGGER = Invidious::LogHandler.new(OUTPUT, CONFIG.log_level) | ||||
|  | ||||
| # Run migrations | ||||
| Invidious::Migrator.new(PG_DB).migrate | ||||
| Invidious::Database::Migrator.new(PG_DB).migrate | ||||
| # Check table integrity | ||||
| Invidious::Database.check_integrity(CONFIG) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| abstract class Invidious::Migration | ||||
| abstract class Invidious::Database::Migration | ||||
|   macro inherited | ||||
|     Invidious::Migrator.migrations << self | ||||
|     Migrator.migrations << self | ||||
|   end | ||||
| 
 | ||||
|   @@version : Int64? | ||||
| @@ -33,6 +33,6 @@ abstract class Invidious::Migration | ||||
|   end | ||||
| 
 | ||||
|   private def track(conn : DB::Connection) | ||||
|     conn.exec("INSERT INTO #{Invidious::Migrator::MIGRATIONS_TABLE}(version) VALUES ($1)", version) | ||||
|     conn.exec("INSERT INTO #{Migrator::MIGRATIONS_TABLE} (version) VALUES ($1)", version) | ||||
|   end | ||||
| end | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateChannelsTable < Migration | ||||
|     version 0 | ||||
|     version 1 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateVideosTable < Migration | ||||
|     version 1 | ||||
|     version 2 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateChannelVideosTable < Migration | ||||
|     version 2 | ||||
|     version 3 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateUsersTable < Migration | ||||
|     version 3 | ||||
|     version 4 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateSessionIdsTable < Migration | ||||
|     version 4 | ||||
|     version 5 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateNoncesTable < Migration | ||||
|     version 5 | ||||
|     version 6 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -1,6 +1,6 @@ | ||||
| module Invidious::Migrations | ||||
| module Invidious::Database::Migrations | ||||
|   class CreateAnnotationsTable < Migration | ||||
|     version 6 | ||||
|     version 7 | ||||
| 
 | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
| @@ -0,0 +1,50 @@ | ||||
| module Invidious::Database::Migrations | ||||
|   class CreatePlaylistsTable < Migration | ||||
|     version 8 | ||||
|  | ||||
|     def up(conn : DB::Connection) | ||||
|       if !privacy_type_exists?(conn) | ||||
|         conn.exec <<-SQL | ||||
|         CREATE TYPE public.privacy AS ENUM | ||||
|         ( | ||||
|           'Public', | ||||
|           'Unlisted', | ||||
|           'Private' | ||||
|         ); | ||||
|         SQL | ||||
|       end | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS public.playlists | ||||
|       ( | ||||
|         title text, | ||||
|         id text primary key, | ||||
|         author text, | ||||
|         description text, | ||||
|         video_count integer, | ||||
|         created timestamptz, | ||||
|         updated timestamptz, | ||||
|         privacy privacy, | ||||
|         index int8[] | ||||
|       ); | ||||
|       SQL | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       GRANT ALL ON public.playlists TO current_user; | ||||
|       SQL | ||||
|     end | ||||
|  | ||||
|     private def privacy_type_exists?(conn : DB::Connection) : Bool | ||||
|       request = <<-SQL | ||||
|         SELECT 1 AS one | ||||
|         FROM pg_type | ||||
|         INNER JOIN pg_namespace ON pg_namespace.oid = pg_type.typnamespace | ||||
|         WHERE pg_namespace.nspname = 'public' | ||||
|           AND pg_type.typname = 'privacy' | ||||
|         LIMIT 1; | ||||
|       SQL | ||||
|  | ||||
|       !conn.query_one?(request, as: Int32).nil? | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -0,0 +1,27 @@ | ||||
| module Invidious::Database::Migrations | ||||
|   class CreatePlaylistVideosTable < Migration | ||||
|     version 9 | ||||
|  | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS public.playlist_videos | ||||
|       ( | ||||
|         title text, | ||||
|         id text, | ||||
|         author text, | ||||
|         ucid text, | ||||
|         length_seconds integer, | ||||
|         published timestamptz, | ||||
|         plid text references playlists(id), | ||||
|         index int8, | ||||
|         live_now boolean, | ||||
|         PRIMARY KEY (index,plid) | ||||
|       ); | ||||
|       SQL | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       GRANT ALL ON TABLE public.playlist_videos TO current_user; | ||||
|       SQL | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -0,0 +1,11 @@ | ||||
| module Invidious::Database::Migrations | ||||
|   class MakeVideosUnlogged < Migration | ||||
|     version 10 | ||||
|  | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
|       ALTER TABLE public.videos SET UNLOGGED; | ||||
|       SQL | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										42
									
								
								src/invidious/database/migrator.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/invidious/database/migrator.cr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| class Invidious::Database::Migrator | ||||
|   MIGRATIONS_TABLE = "public.invidious_migrations" | ||||
|  | ||||
|   class_getter migrations = [] of Invidious::Database::Migration.class | ||||
|  | ||||
|   def initialize(@db : DB::Database) | ||||
|   end | ||||
|  | ||||
|   def migrate | ||||
|     versions = load_versions | ||||
|  | ||||
|     ran_migration = false | ||||
|     load_migrations.sort_by(&.version) | ||||
|       .each do |migration| | ||||
|         next if versions.includes?(migration.version) | ||||
|  | ||||
|         puts "Running migration: #{migration.class.name}" | ||||
|         migration.migrate | ||||
|         ran_migration = true | ||||
|       end | ||||
|  | ||||
|     puts "No migrations to run." unless ran_migration | ||||
|   end | ||||
|  | ||||
|   private def load_migrations : Array(Invidious::Database::Migration) | ||||
|     self.class.migrations.map(&.new(@db)) | ||||
|   end | ||||
|  | ||||
|   private def load_versions : Array(Int64) | ||||
|     create_migrations_table | ||||
|     @db.query_all("SELECT version FROM #{MIGRATIONS_TABLE}", as: Int64) | ||||
|   end | ||||
|  | ||||
|   private def create_migrations_table | ||||
|     @db.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS #{MIGRATIONS_TABLE} ( | ||||
|         id bigserial PRIMARY KEY, | ||||
|         version bigint NOT NULL | ||||
|       ) | ||||
|     SQL | ||||
|   end | ||||
| end | ||||
| @@ -1,47 +0,0 @@ | ||||
| module Invidious::Migrations | ||||
|   class CreatePlaylistsTable < Migration | ||||
|     version 7 | ||||
|  | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
|       DO | ||||
|       $$ | ||||
|       BEGIN | ||||
|         IF NOT EXISTS (SELECT * | ||||
|                         FROM pg_type typ | ||||
|                         INNER JOIN pg_namespace nsp ON nsp.oid = typ.typnamespace | ||||
|                         WHERE nsp.nspname = 'public' | ||||
|                               AND typ.typname = 'privacy') THEN | ||||
|           CREATE TYPE public.privacy AS ENUM | ||||
|             ( | ||||
|                 'Public', | ||||
|                 'Unlisted', | ||||
|                 'Private' | ||||
|             ); | ||||
|         END IF; | ||||
|       END; | ||||
|       $$ | ||||
|       LANGUAGE plpgsql; | ||||
|       SQL | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS public.playlists | ||||
|       ( | ||||
|           title text, | ||||
|           id text primary key, | ||||
|           author text, | ||||
|           description text, | ||||
|           video_count integer, | ||||
|           created timestamptz, | ||||
|           updated timestamptz, | ||||
|           privacy privacy, | ||||
|           index int8[] | ||||
|       ); | ||||
|       SQL | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       GRANT ALL ON public.playlists TO current_user; | ||||
|       SQL | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -1,27 +0,0 @@ | ||||
| module Invidious::Migrations | ||||
|   class CreatePlaylistVideosTable < Migration | ||||
|     version 8 | ||||
|  | ||||
|     def up(conn : DB::Connection) | ||||
|       conn.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS public.playlist_videos | ||||
|       ( | ||||
|             title text, | ||||
|             id text, | ||||
|             author text, | ||||
|             ucid text, | ||||
|             length_seconds integer, | ||||
|             published timestamptz, | ||||
|             plid text references playlists(id), | ||||
|             index int8, | ||||
|             live_now boolean, | ||||
|             PRIMARY KEY (index,plid) | ||||
|         ); | ||||
|       SQL | ||||
|  | ||||
|       conn.exec <<-SQL | ||||
|       GRANT ALL ON TABLE public.playlist_videos TO current_user; | ||||
|       SQL | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -1,41 +0,0 @@ | ||||
| class Invidious::Migrator | ||||
|   MIGRATIONS_TABLE = "invidious_migrations" | ||||
|  | ||||
|   class_getter migrations = [] of Invidious::Migration.class | ||||
|  | ||||
|   def initialize(@db : DB::Database) | ||||
|   end | ||||
|  | ||||
|   def migrate | ||||
|     run_migrations = load_run_migrations | ||||
|     migrations = load_migrations.sort_by(&.version) | ||||
|     migrations_to_run = migrations.reject { |migration| run_migrations.includes?(migration.version) } | ||||
|     if migrations.empty? | ||||
|       puts "No migrations to run." | ||||
|       return | ||||
|     end | ||||
|  | ||||
|     migrations_to_run.each do |migration| | ||||
|       puts "Running migration: #{migration.class.name}" | ||||
|       migration.migrate | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   private def load_migrations : Array(Invidious::Migration) | ||||
|     self.class.migrations.map(&.new(@db)) | ||||
|   end | ||||
|  | ||||
|   private def load_run_migrations : Array(Int64) | ||||
|     create_migrations_table | ||||
|     @db.query_all("SELECT version FROM #{MIGRATIONS_TABLE}", as: Int64) | ||||
|   end | ||||
|  | ||||
|   private def create_migrations_table | ||||
|     @db.exec <<-SQL | ||||
|       CREATE TABLE IF NOT EXISTS #{MIGRATIONS_TABLE} ( | ||||
|         id bigserial PRIMARY KEY, | ||||
|         version bigint NOT NULL | ||||
|       ) | ||||
|     SQL | ||||
|   end | ||||
| end | ||||
		Reference in New Issue
	
	Block a user
	 matthewmcgarvey
					matthewmcgarvey