diff options
| author | Joshua M. Boniface <joshua@boniface.me> | 2020-03-05 10:03:43 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-05 10:03:43 -0500 |
| commit | dcf3dbb2507f9e6a213b62b47cf8c327873f78b1 (patch) | |
| tree | 3022ca1868877ae01618a371e9489c6f9b39cc4a | |
| parent | ca585f12b3297f58e8f490b03b64729716eb2f40 (diff) | |
| parent | 9eef0e8ca0e3359239ab68fcadbf2d65084f12e6 (diff) | |
Merge pull request #2515 from JustAMan/migration-scripts
Implement ability to run migration routines when updating Jellyfin
| -rw-r--r-- | Jellyfin.Server/CoreAppHost.cs | 28 | ||||
| -rw-r--r-- | Jellyfin.Server/Migrations.cs | 92 | ||||
| -rw-r--r-- | Jellyfin.Server/Program.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs | 21 |
4 files changed, 142 insertions, 0 deletions
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 8b4b61e29..cd5a2ce85 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -57,5 +57,33 @@ namespace Jellyfin.Server /// <inheritdoc /> protected override void ShutdownInternal() => Program.Shutdown(); + + /// <summary> + /// Runs the migration routines if necessary. + /// </summary> + public void TryMigrate() + { + var previousVersion = ConfigurationManager.CommonConfiguration.PreviousVersion; + switch (ApplicationVersion.CompareTo(previousVersion)) + { + case 1: + Logger.LogWarning("Version check shows Jellyfin was updated: previous version={0}, current version={1}", previousVersion, ApplicationVersion); + + Migrations.Run(this, Logger); + + ConfigurationManager.CommonConfiguration.PreviousVersion = ApplicationVersion; + ConfigurationManager.SaveConfiguration(); + break; + case 0: + // nothing to do, versions match + break; + case -1: + Logger.LogWarning("Version check shows Jellyfin was rolled back, use at your own risk: previous version={0}, current version={1}", previousVersion, ApplicationVersion); + // no "rollback" routines for now + ConfigurationManager.CommonConfiguration.PreviousVersion = ApplicationVersion; + ConfigurationManager.SaveConfiguration(); + break; + } + } } } diff --git a/Jellyfin.Server/Migrations.cs b/Jellyfin.Server/Migrations.cs new file mode 100644 index 000000000..95fea4ea5 --- /dev/null +++ b/Jellyfin.Server/Migrations.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server +{ + /// <summary> + /// The class that knows how migrate between different Jellyfin versions. + /// </summary> + internal static class Migrations + { + private static readonly IUpdater[] _migrations = + { + new Pre10_5() + }; + + /// <summary> + /// Interface that descibes a migration routine. + /// </summary> + private interface IUpdater + { + /// <summary> + /// Gets maximum version this Updater applies to. + /// If current version is greater or equal to it, skip the updater. + /// </summary> + public abstract Version Maximum { get; } + + /// <summary> + /// Execute the migration from version "from". + /// </summary> + /// <param name="host">Host that hosts current version.</param> + /// <param name="logger">Host logger.</param> + /// <param name="from">Version to migrate from.</param> + /// <returns>Whether configuration was changed.</returns> + public abstract bool Perform(CoreAppHost host, ILogger logger, Version from); + } + + /// <summary> + /// Run all needed migrations. + /// </summary> + /// <param name="host">CoreAppHost that hosts current version.</param> + /// <param name="logger">AppHost logger.</param> + /// <returns>Whether anything was changed.</returns> + public static bool Run(CoreAppHost host, ILogger logger) + { + bool updated = false; + var version = host.ServerConfigurationManager.CommonConfiguration.PreviousVersion; + + for (var i = 0; i < _migrations.Length; i++) + { + var updater = _migrations[i]; + if (version.CompareTo(updater.Maximum) >= 0) + { + logger.LogDebug("Skipping updater {0} as current version {1} >= its maximum applicable version {2}", updater, version, updater.Maximum); + continue; + } + + if (updater.Perform(host, logger, version)) + { + updated = true; + } + + version = updater.Maximum; + } + + return updated; + } + + private class Pre10_5 : IUpdater + { + public Version Maximum { get => Version.Parse("10.5.0"); } + + public bool Perform(CoreAppHost host, ILogger logger, Version from) + { + // Set EnableThrottling to false as it wasn't used before, and in 10.5.0 it may introduce issues + var encoding = ((IConfigurationManager)host.ServerConfigurationManager).GetConfiguration<EncodingOptions>("encoding"); + if (encoding.EnableThrottling) + { + logger.LogInformation("Disabling transcoding throttling during migration"); + encoding.EnableThrottling = false; + + host.ServerConfigurationManager.SaveConfiguration("encoding", encoding); + return true; + } + + return false; + } + } + } +} diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 484e507a2..aa1bdb169 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -182,6 +182,7 @@ namespace Jellyfin.Server // A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection. appHost.ServiceProvider = host.Services; appHost.FindParts(); + appHost.TryMigrate(); try { diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index 6a1a0f090..cc2541f74 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -1,3 +1,6 @@ +using System; +using System.Xml.Serialization; + namespace MediaBrowser.Model.Configuration { /// <summary> @@ -26,6 +29,24 @@ namespace MediaBrowser.Model.Configuration public string CachePath { get; set; } /// <summary> + /// Last known version that was ran using the configuration. + /// </summary> + /// <value>The version from previous run.</value> + [XmlIgnore] + public Version PreviousVersion { get; set; } + + /// <summary> + /// Stringified PreviousVersion to be stored/loaded, + /// because System.Version itself isn't xml-serializable + /// </summary> + /// <value>String value of PreviousVersion</value> + public string PreviousVersionStr + { + get => PreviousVersion?.ToString(); + set => PreviousVersion = Version.Parse(value); + } + + /// <summary> /// Initializes a new instance of the <see cref="BaseApplicationConfiguration" /> class. /// </summary> public BaseApplicationConfiguration() |
