From 15d564af52d8d54e3b016b8960bb0b42c5df5a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 14 Nov 2024 23:49:09 +0100 Subject: [PATCH] Improve how package managers handle first failures. Add a AttemptFastRepair method (fix #2920) --- .../IPackageManager.cs | 9 +++++++ .../WinGet.cs | 22 +++++++++++++++ .../Manager/Classes/NullPackageManager.cs | 5 ++++ .../Manager/PackageManager.cs | 27 ++++++++++++++++--- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs b/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs index cd0be0bb8..28bee7aad 100644 --- a/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs +++ b/src/UniGetUI.PAckageEngine.Interfaces/IPackageManager.cs @@ -59,6 +59,15 @@ public interface IPackageManager : ISourceProvider, IPackageDetailsProvider, IOp /// public void RefreshPackageIndexes(); + /// + /// This method should attempt to resolve issues + /// such as COM API disconnect or similar issues that + /// can easily be resolved by reconnecting to a client and/or + /// clearing some internal caches. See the WinGet implementation for + /// an example + /// + public void AttemptFastRepair(); + public IManagerSource GetSourceOrDefault(string SourceName); public IManagerSource? GetSourceIfExists(string SourceName); } diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs index a715bef3c..9ba3741cb 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs @@ -239,6 +239,28 @@ private void ReRegisterCOMServer() NativePackageHandler.Clear(); } + public override void AttemptFastRepair() + { + try + { + if (WinGetHelper.Instance is NativeWinGetHelper) + { + Logger.ImportantInfo("Attempting to reconnec to WinGet COM Server..."); + ReRegisterCOMServer(); + NO_PACKAGES_HAVE_BEEN_LOADED = false; + } + else + { + Logger.Warn("Attempted to reconnect to COM Server but Bundled WinGet is being used."); + } + } catch (Exception ex) + { + Logger.Error("An error ocurred while attempting to reconnect to COM Server"); + Logger.Error(ex); + } + } + + public override void RefreshPackageIndexes() { diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs index 7892d7f32..7cf842501 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs @@ -208,6 +208,11 @@ public OperationVeredict GetOperationResult(IPackage package, OperationType oper { throw new NotImplementedException(); } + + public void AttemptFastRepair() + { + throw new NotImplementedException(); + } } internal sealed class NullSourceProvider : BaseSourceProvider diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index 4ae4bba38..e973932eb 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -181,7 +181,13 @@ private IEnumerable _findPackages(string query, bool SecondAttempt) catch (Exception e) { if (!SecondAttempt) + { + while (e is AggregateException) e = e.InnerException ?? new("How did we get here?"); + Logger.Warn($"Manager {DisplayName} failed to find packages with exception {e.GetType().Name}: {e.Message}"); + Logger.Warn($"Since this was the first attempt, {Name}.AttemptFastRepair() will be called and the procedure will be restarted"); + AttemptFastRepair(); return _findPackages(query, true); + } else { Logger.Error("Error finding packages on manager " + Name + " with query " + query); @@ -199,9 +205,6 @@ public IEnumerable GetAvailableUpdates() => _getAvailableUpdates(false); private IEnumerable _getAvailableUpdates(bool SecondAttempt) - /* => TaskRecycler>.RunOrAttach(_getAvailableUpdates, Properties.Name.GetHashCode()); - - private IEnumerable _getAvailableUpdates(int _uselessParam)*/ { if (!IsReady()) { Logger.Warn($"Manager {Name} is disabled but yet GetAvailableUpdates was called"); return []; } try @@ -225,7 +228,13 @@ private IEnumerable _getAvailableUpdates(int _uselessParam)*/ catch (Exception e) { if (!SecondAttempt) + { + while (e is AggregateException) e = e.InnerException ?? new("How did we get here?"); + Logger.Warn($"Manager {DisplayName} failed to list available updates with exception {e.GetType().Name}: {e.Message}"); + Logger.Warn($"Since this was the first attempt, {Name}.AttemptFastRepair() will be called and the procedure will be restarted"); + AttemptFastRepair(); return _getAvailableUpdates(true); + } else { Logger.Error("Error finding updates on manager " + Name); @@ -264,7 +273,13 @@ private IEnumerable _getInstalledPackages(bool SecondAttempt) catch (Exception e) { if (!SecondAttempt) + { + while (e is AggregateException) e = e.InnerException ?? new("How did we get here?"); + Logger.Warn($"Manager {DisplayName} failed to list installed packages with exception {e.GetType().Name}: {e.Message}"); + Logger.Warn($"Since this was the first attempt, {Name}.AttemptFastRepair() will be called and the procedure will be restarted"); + AttemptFastRepair(); return _getInstalledPackages(true); + } else { Logger.Error("Error finding installed packages on manager " + Name); @@ -306,6 +321,12 @@ public virtual async void RefreshPackageIndexes() await Task.CompletedTask; } + public virtual void AttemptFastRepair() + { + // Implementing this method is optional + } + + // BEGIN SOURCE-RELATED METHODS ///