diff --git a/src/Artemis.Core/Plugins/PluginFeature.cs b/src/Artemis.Core/Plugins/PluginFeature.cs index ef3917ba0..149d42632 100644 --- a/src/Artemis.Core/Plugins/PluginFeature.cs +++ b/src/Artemis.Core/Plugins/PluginFeature.cs @@ -12,7 +12,7 @@ namespace Artemis.Core { private bool _isEnabled; - + /// /// Gets the plugin feature info related to this feature /// @@ -37,6 +37,8 @@ namespace Artemis.Core internal set => SetAndNotify(ref _isEnabled, value); } + internal int AutoEnableAttempts { get; set; } + /// /// Gets the identifier of this plugin feature /// @@ -137,6 +139,9 @@ namespace Artemis.Core try { + if (isAutoEnable) + AutoEnableAttempts++; + if (isAutoEnable && GetLockFileCreated()) { // Don't wrap existing lock exceptions, simply rethrow them @@ -157,6 +162,7 @@ namespace Artemis.Core throw new ArtemisPluginException(Plugin, "Plugin load timeout"); Info.LoadException = null; + AutoEnableAttempts = 0; OnEnabled(); } // If enable failed, put it back in a disabled state diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs index de01c754f..5e4841829 100644 --- a/src/Artemis.Core/Services/PluginManagementService.cs +++ b/src/Artemis.Core/Services/PluginManagementService.cs @@ -5,6 +5,7 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Artemis.Core.DeviceProviders; using Artemis.Core.Ninject; using Artemis.Storage.Entities.General; @@ -90,7 +91,7 @@ namespace Artemis.Core.Services using StreamReader reader = new(metaDataFileEntry.Open()); PluginInfo builtInPluginInfo = CoreJson.DeserializeObject(reader.ReadToEnd())!; string preferred = builtInPluginInfo.PreferredPluginDirectory; - + // Find the matching plugin in the plugin folder DirectoryInfo? match = pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == preferred); if (match == null) @@ -610,13 +611,38 @@ namespace Artemis.Core.Services } catch (Exception e) { - _logger.Warning( - new ArtemisPluginException(pluginFeature.Plugin, $"Exception during SetEnabled(true) on {pluginFeature}", e), - "Failed to enable plugin" - ); + if (isAutoEnable) + { + // Schedule a retry based on the amount of attempts + if (pluginFeature.AutoEnableAttempts < 4) + { + TimeSpan retryDelay = TimeSpan.FromSeconds(pluginFeature.AutoEnableAttempts * 10); + _logger.Warning( + e, + "Plugin feature '{feature} - {plugin}' failed to enable during attempt ({attempt}/3), scheduling a retry in {retryDelay}.", + pluginFeature, + pluginFeature.Plugin, + pluginFeature.AutoEnableAttempts, + retryDelay + ); - if (!isAutoEnable) + Task.Run(async () => + { + await Task.Delay(retryDelay); + if (!pluginFeature.IsEnabled) + EnablePluginFeature(pluginFeature, saveState, true); + }); + } + else + { + _logger.Warning(e, "Plugin feature '{feature} - {plugin}' failed to enable after 3 attempts, giving up.", pluginFeature, pluginFeature.Plugin); + } + } + else + { + _logger.Warning(e, "Plugin feature '{feature} - {plugin}' failed to enable.", pluginFeature, pluginFeature.Plugin); throw; + } } finally {