From 8129773d69d7e8d4c27c3783bf8cf5f962da30e1 Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Sat, 21 Oct 2023 18:37:01 -0400 Subject: [PATCH] Extract symlinking behavior to `SymlinkDmbProvider` --- .../Deployment/HardLinkDmbProvider.cs | 16 ++++--- .../Deployment/SwappableDmbProvider.cs | 44 +++++++------------ .../Deployment/SymlinkDmbProvider.cs | 44 +++++++++++++++++++ .../Components/Watchdog/WindowsWatchdog.cs | 2 +- 4 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 src/Tgstation.Server.Host/Components/Deployment/SymlinkDmbProvider.cs diff --git a/src/Tgstation.Server.Host/Components/Deployment/HardLinkDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/HardLinkDmbProvider.cs index e5ddede026..634af753f4 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/HardLinkDmbProvider.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/HardLinkDmbProvider.cs @@ -111,15 +111,17 @@ namespace Tgstation.Server.Host.Components.Deployment goAheadTcs.SetResult(); await IOManager.DeleteDirectory(disposePath, CancellationToken.None); // DCT: We're detached at this point } + catch (DirectoryNotFoundException ex) + { + logger.LogDebug(ex, "Live directory appears to not exist"); + if (!directoryMoved) + goAheadTcs.SetResult(); + } catch (Exception ex) { - if (directoryMoved) - logger.LogWarning(ex, "Failed to delete hard linked directory: {disposePath}", disposePath); - else - { - logger.LogDebug(ex, "Live directory appears to not exist"); - goAheadTcs.SetResult(); - } + logger.LogWarning(ex, "Failed to delete hard linked directory: {disposePath}", disposePath); + if (!directoryMoved) + goAheadTcs.SetException(ex); } } diff --git a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs index 14cdc268e2..b82f5cc676 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs @@ -8,29 +8,34 @@ using Tgstation.Server.Host.Models; namespace Tgstation.Server.Host.Components.Deployment { /// - /// A that uses symlinks. + /// A that uses filesystem links to change directory structure underneath the server process. /// - class SwappableDmbProvider : IDmbProvider + abstract class SwappableDmbProvider : IDmbProvider { /// - /// The directory where the is symlinked to. + /// The directory where the is symlinked to. /// public const string LiveGameDirectory = "Live"; /// - public string DmbName => baseProvider.DmbName; + public string DmbName => BaseProvider.DmbName; /// public string Directory => IOManager.ResolvePath(LiveGameDirectory); /// - public CompileJob CompileJob => baseProvider.CompileJob; + public CompileJob CompileJob => BaseProvider.CompileJob; /// /// If has been run. /// public bool Swapped => swapped != 0; + /// + /// The we are swapping for. + /// + protected IDmbProvider BaseProvider { get; } + /// /// The to use. /// @@ -41,11 +46,6 @@ namespace Tgstation.Server.Host.Components.Deployment /// protected ISymlinkFactory SymlinkFactory { get; } - /// - /// The we are swapping for. - /// - readonly IDmbProvider baseProvider; - /// /// Backing field for . /// @@ -54,21 +54,21 @@ namespace Tgstation.Server.Host.Components.Deployment /// /// Initializes a new instance of the class. /// - /// The value of . + /// The value of . /// The value of . /// The value of . public SwappableDmbProvider(IDmbProvider baseProvider, IIOManager ioManager, ISymlinkFactory symlinkFactory) { - this.baseProvider = baseProvider ?? throw new ArgumentNullException(nameof(baseProvider)); + BaseProvider = baseProvider ?? throw new ArgumentNullException(nameof(baseProvider)); IOManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); SymlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory)); } /// - public virtual ValueTask DisposeAsync() => baseProvider.DisposeAsync(); + public virtual ValueTask DisposeAsync() => BaseProvider.DisposeAsync(); /// - public void KeepAlive() => baseProvider.KeepAlive(); + public void KeepAlive() => BaseProvider.KeepAlive(); /// /// Make the active by replacing the live link with our . @@ -88,25 +88,13 @@ namespace Tgstation.Server.Host.Components.Deployment /// /// The for the operation. /// A representing the preparation process. - public virtual Task FinishActivationPreparation(CancellationToken cancellationToken) - => Task.CompletedTask; + public abstract Task FinishActivationPreparation(CancellationToken cancellationToken); /// /// Perform the swapping action. /// /// The for the operation. /// A representing the running operation. - protected virtual async Task DoSwap(CancellationToken cancellationToken) - { - if (SymlinkFactory.SymlinkedDirectoriesAreDeletedAsFiles) - await IOManager.DeleteFile(LiveGameDirectory, cancellationToken); - else - await IOManager.DeleteDirectory(LiveGameDirectory, cancellationToken); - - await SymlinkFactory.CreateSymbolicLink( - IOManager.ResolvePath(baseProvider.Directory), - IOManager.ResolvePath(LiveGameDirectory), - cancellationToken); - } + protected abstract Task DoSwap(CancellationToken cancellationToken); } } diff --git a/src/Tgstation.Server.Host/Components/Deployment/SymlinkDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/SymlinkDmbProvider.cs new file mode 100644 index 0000000000..7e0845b95c --- /dev/null +++ b/src/Tgstation.Server.Host/Components/Deployment/SymlinkDmbProvider.cs @@ -0,0 +1,44 @@ +using System.Threading; +using System.Threading.Tasks; + +using Tgstation.Server.Host.IO; + +namespace Tgstation.Server.Host.Components.Deployment +{ + /// + /// A that uses symlinks. + /// + sealed class SymlinkDmbProvider : SwappableDmbProvider + { + /// + /// Initializes a new instance of the class. + /// + /// The for the . + /// The for the . + /// The for the . + public SymlinkDmbProvider( + IDmbProvider baseProvider, + IIOManager ioManager, + ISymlinkFactory symlinkFactory) + : base(baseProvider, ioManager, symlinkFactory) + { + } + + /// + public override Task FinishActivationPreparation(CancellationToken cancellationToken) => Task.CompletedTask; + + /// + protected override async Task DoSwap(CancellationToken cancellationToken) + { + if (SymlinkFactory.SymlinkedDirectoriesAreDeletedAsFiles) + await IOManager.DeleteFile(LiveGameDirectory, cancellationToken); + else + await IOManager.DeleteDirectory(LiveGameDirectory, cancellationToken); + + await SymlinkFactory.CreateSymbolicLink( + IOManager.ResolvePath(BaseProvider.Directory), + IOManager.ResolvePath(LiveGameDirectory), + cancellationToken); + } + } +} diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdog.cs b/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdog.cs index 917bafa134..d882296b06 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdog.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WindowsWatchdog.cs @@ -85,6 +85,6 @@ namespace Tgstation.Server.Host.Components.Watchdog /// protected override SwappableDmbProvider CreateSwappableDmbProvider(IDmbProvider dmbProvider) - => new SwappableDmbProvider(dmbProvider, GameIOManager, SymlinkFactory); + => new SymlinkDmbProvider(dmbProvider, GameIOManager, SymlinkFactory); } }