aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Migrations/Stages
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2025-04-28 03:18:08 +0300
committerGitHub <noreply@github.com>2025-04-27 18:18:08 -0600
commite66c76fc3405512b90735b5669278410f7974b1f (patch)
treeb7329723558336c991524ee1d768ecf2af93be58 /Jellyfin.Server/Migrations/Stages
parent1c4b5199b8fa42dd41d6d779db98650a460c7117 (diff)
Unified migration handling (#13950)
Diffstat (limited to 'Jellyfin.Server/Migrations/Stages')
-rw-r--r--Jellyfin.Server/Migrations/Stages/CodeMigration.cs51
-rw-r--r--Jellyfin.Server/Migrations/Stages/JellyfinMigrationStageTypes.cs26
-rw-r--r--Jellyfin.Server/Migrations/Stages/MigrationStage.cs16
3 files changed, 93 insertions, 0 deletions
diff --git a/Jellyfin.Server/Migrations/Stages/CodeMigration.cs b/Jellyfin.Server/Migrations/Stages/CodeMigration.cs
new file mode 100644
index 000000000..1e4dfb237
--- /dev/null
+++ b/Jellyfin.Server/Migrations/Stages/CodeMigration.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Jellyfin.Server.Migrations.Stages;
+
+internal class CodeMigration(Type migrationType, JellyfinMigrationAttribute metadata)
+{
+ public Type MigrationType { get; } = migrationType;
+
+ public JellyfinMigrationAttribute Metadata { get; } = metadata;
+
+ public string BuildCodeMigrationId()
+ {
+ return Metadata.Order.ToString("yyyyMMddHHmmsss", CultureInfo.InvariantCulture) + "_" + MigrationType.Name!;
+ }
+
+ public async Task Perform(IServiceProvider? serviceProvider, CancellationToken cancellationToken)
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ if (typeof(IMigrationRoutine).IsAssignableFrom(MigrationType))
+ {
+ if (serviceProvider is null)
+ {
+ ((IMigrationRoutine)Activator.CreateInstance(MigrationType)!).Perform();
+ }
+ else
+ {
+ ((IMigrationRoutine)ActivatorUtilities.CreateInstance(serviceProvider, MigrationType)).Perform();
+#pragma warning restore CS0618 // Type or member is obsolete
+ }
+ }
+ else if (typeof(IAsyncMigrationRoutine).IsAssignableFrom(MigrationType))
+ {
+ if (serviceProvider is null)
+ {
+ await ((IAsyncMigrationRoutine)Activator.CreateInstance(MigrationType)!).PerformAsync(cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ await ((IAsyncMigrationRoutine)ActivatorUtilities.CreateInstance(serviceProvider, MigrationType)).PerformAsync(cancellationToken).ConfigureAwait(false);
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException($"The type {MigrationType} does not implement either IMigrationRoutine or IAsyncMigrationRoutine and is not a valid migration type");
+ }
+ }
+}
diff --git a/Jellyfin.Server/Migrations/Stages/JellyfinMigrationStageTypes.cs b/Jellyfin.Server/Migrations/Stages/JellyfinMigrationStageTypes.cs
new file mode 100644
index 000000000..d90ad3d9b
--- /dev/null
+++ b/Jellyfin.Server/Migrations/Stages/JellyfinMigrationStageTypes.cs
@@ -0,0 +1,26 @@
+namespace Jellyfin.Server.Migrations.Stages;
+
+/// <summary>
+/// Defines the stages the <see cref="JellyfinMigrationService"/> supports.
+/// </summary>
+#pragma warning disable CA1008 // Enums should have zero value
+public enum JellyfinMigrationStageTypes
+#pragma warning restore CA1008 // Enums should have zero value
+{
+ /// <summary>
+ /// Runs before services are initialised.
+ /// Reserved for migrations that are modifying the application server itself. Should be avoided if possible.
+ /// </summary>
+ PreInitialisation = 1,
+
+ /// <summary>
+ /// Runs after the host has been configured and includes the database migrations.
+ /// Allows the mix order of migrations that contain application code and database changes.
+ /// </summary>
+ CoreInitialisaition = 2,
+
+ /// <summary>
+ /// Runs after services has been registered and initialised. Last step before running the server.
+ /// </summary>
+ AppInitialisation = 3
+}
diff --git a/Jellyfin.Server/Migrations/Stages/MigrationStage.cs b/Jellyfin.Server/Migrations/Stages/MigrationStage.cs
new file mode 100644
index 000000000..efcadbf00
--- /dev/null
+++ b/Jellyfin.Server/Migrations/Stages/MigrationStage.cs
@@ -0,0 +1,16 @@
+using System.Collections.ObjectModel;
+
+namespace Jellyfin.Server.Migrations.Stages;
+
+/// <summary>
+/// Defines a Stage that can be Invoked and Handled at different times from the code.
+/// </summary>
+internal class MigrationStage : Collection<CodeMigration>
+{
+ public MigrationStage(JellyfinMigrationStageTypes stage)
+ {
+ Stage = stage;
+ }
+
+ public JellyfinMigrationStageTypes Stage { get; }
+}