diff --git a/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs b/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs new file mode 100644 index 000000000..464ff5ff4 --- /dev/null +++ b/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs @@ -0,0 +1,8 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Lifecycle +{ + public class ApplicationStartingEvent : IEvent + { + } +} diff --git a/src/NzbDrone.Core/Update/InstallUpdateService.cs b/src/NzbDrone.Core/Update/InstallUpdateService.cs index 74e53142b..bea565573 100644 --- a/src/NzbDrone.Core/Update/InstallUpdateService.cs +++ b/src/NzbDrone.Core/Update/InstallUpdateService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Threading; using NLog; using NzbDrone.Common; using NzbDrone.Common.Disk; @@ -11,12 +13,14 @@ using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Processes; using NzbDrone.Core.Backup; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Update.Commands; namespace NzbDrone.Core.Update { - public class InstallUpdateService : IExecute, IExecute + public class InstallUpdateService : IExecute, IExecute, IHandle { private readonly ICheckUpdateService _checkUpdateService; private readonly Logger _logger; @@ -75,7 +79,7 @@ namespace NzbDrone.Core.Update _logger = logger; } - private void InstallUpdate(UpdatePackage updatePackage) + private bool InstallUpdate(UpdatePackage updatePackage) { EnsureAppDataSafety(); @@ -95,6 +99,12 @@ namespace NzbDrone.Core.Update } } + if (_appFolderInfo.StartUpFolder.EndsWith("_output")) + { + _logger.ProgressDebug("Running in developer environment, not updating."); + return false; + } + var updateSandboxFolder = _appFolderInfo.GetUpdateSandboxFolder(); var packageDestination = Path.Combine(updateSandboxFolder, updatePackage.FileName); @@ -130,7 +140,7 @@ namespace NzbDrone.Core.Update if (OsInfo.IsNotWindows && _configFileProvider.UpdateMechanism == UpdateMechanism.Script) { InstallUpdateWithScript(updateSandboxFolder); - return; + return true; } _logger.Info("Preparing client"); @@ -146,6 +156,8 @@ namespace NzbDrone.Core.Update _logger.ProgressInfo("Readarr will restart shortly."); _processProvider.Start(_appFolderInfo.GetUpdateClientExePath(updatePackage.Runtime), GetUpdaterArgs(updateSandboxFolder)); + + return true; } private void EnsureValidBranch(UpdatePackage package) @@ -281,5 +293,63 @@ namespace NzbDrone.Core.Update } } } + + public void Handle(ApplicationStartingEvent message) + { + // Check if we have to do an application update on startup + try + { + // Don't do a prestartup update check unless BuiltIn update is enabled + if (_configFileProvider.UpdateAutomatically || + _configFileProvider.UpdateMechanism != UpdateMechanism.BuiltIn || + _deploymentInfoProvider.IsExternalUpdateMechanism) + { + return; + } + + var updateMarker = Path.Combine(_appFolderInfo.AppDataFolder, "update_required"); + if (!_diskProvider.FileExists(updateMarker)) + { + return; + } + + _logger.Debug("Post-install update check requested"); + + var latestAvailable = _checkUpdateService.AvailableUpdate(); + if (latestAvailable == null) + { + _logger.Debug("No post-install update available"); + _diskProvider.DeleteFile(updateMarker); + return; + } + + _logger.Info("Installing post-install update from {0} to {1}", BuildInfo.Version, latestAvailable.Version); + _diskProvider.DeleteFile(updateMarker); + + var installing = InstallUpdate(latestAvailable); + + if (installing) + { + _logger.Debug("Install in progress, giving installer 30 seconds."); + + var watch = Stopwatch.StartNew(); + + while (watch.Elapsed < TimeSpan.FromSeconds(30)) + { + Thread.Sleep(1000); + } + + _logger.Error("Post-install update not completed within 30 seconds. Attempting to continue normal operation."); + } + else + { + _logger.Debug("Post-install update cancelled for unknown reason. Attempting to continue normal operation."); + } + } + catch (Exception ex) + { + _logger.Error(ex, "Failed to perform the post-install update check. Attempting to continue normal operation."); + } + } } } diff --git a/src/NzbDrone.Host/Bootstrap.cs b/src/NzbDrone.Host/Bootstrap.cs index 995c55dc5..12389f6f8 100644 --- a/src/NzbDrone.Host/Bootstrap.cs +++ b/src/NzbDrone.Host/Bootstrap.cs @@ -21,6 +21,8 @@ using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore.Extensions; +using NzbDrone.Core.Lifecycle; +using NzbDrone.Core.Messaging.Events; namespace NzbDrone.Host { @@ -128,7 +130,9 @@ namespace NzbDrone.Host c.AutoAddServices(Bootstrap.ASSEMBLIES) .AddNzbDroneLogger() .AddDatabase() - .AddStartupContext(context); + .Resolve().PublishEvent(new ApplicationStartingEvent()); + + c.AddStartupContext(context); }) .ConfigureWebHost(builder => {