diff options
| author | JPVenson <github@jpb.email> | 2025-04-28 03:18:08 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-27 18:18:08 -0600 |
| commit | e66c76fc3405512b90735b5669278410f7974b1f (patch) | |
| tree | b7329723558336c991524ee1d768ecf2af93be58 /Jellyfin.Server/Migrations/Stages | |
| parent | 1c4b5199b8fa42dd41d6d779db98650a460c7117 (diff) | |
Unified migration handling (#13950)
Diffstat (limited to 'Jellyfin.Server/Migrations/Stages')
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; } +} |
