aboutsummaryrefslogtreecommitdiff
path: root/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs')
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs51
1 files changed, 38 insertions, 13 deletions
diff --git a/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs b/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
index 208001a..eb26e92 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
@@ -29,7 +29,6 @@ using System.Linq;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Generic;
-using System.Runtime.CompilerServices;
using VNLib.Utils;
using VNLib.Utils.Logging;
@@ -45,7 +44,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
/// </summary>
internal sealed class PluginManager : VnDisposeable, IHttpPluginManager, IPluginEventListener
{
- private readonly ConditionalWeakTable<PluginController, ManagedPlugin> _managedPlugins;
+ private readonly Dictionary<PluginController, ManagedPlugin> _managedPlugins;
private readonly ServiceDomain _dependents;
private readonly IPluginStack _stack;
@@ -71,7 +70,11 @@ namespace VNLib.Plugins.Essentials.ServiceStack
{
_ = _stack ?? throw new InvalidOperationException("Plugin stack has not been set.");
- //Build the plugin stack
+ /*
+ * Since we own the plugin stack, it is safe to build it here.
+ * This method is not public and should not be called more than
+ * once. Otherwise it can cause issues with the plugin stack.
+ */
_stack.BuildStack();
//Register for plugin events
@@ -83,15 +86,24 @@ namespace VNLib.Plugins.Essentials.ServiceStack
//Add all wrappers to the managed plugins table
Array.ForEach(wrapper, w => _managedPlugins.Add(w.Plugin.Controller, w));
- //Init remaining controllers single-threaded
+ //Init remaining controllers single-threaded because it may mutate the table
_managedPlugins.Select(p => p.Value).TryForeach(w => InitializePlugin(w.Plugin, debugLog));
//Load stage, load all multithreaded
- Parallel.ForEach(wrapper, wp => LoadPlugin(wp.Plugin, debugLog));
+ Parallel.ForEach(_managedPlugins.Values, wp => LoadPlugin(wp.Plugin, debugLog));
debugLog.Information("Plugin loading completed");
}
+ /*
+ * Plugins are manually loaded by this manager instead of the stack shortcut extensions
+ * because I want to catch individual exceptions.
+ *
+ * I do not prefer this method as I would prefer loading is handled by the stack
+ * and the host not by this library.
+ *
+ * This will change in the future.
+ */
private void InitializePlugin(RuntimePluginLoader plugin, ILogProvider debugLog)
{
@@ -108,7 +120,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
*/
if (!plugin.Controller.Plugins.Any())
{
- debugLog.Warn("No plugin instances were exposed via {ams} assembly. This may be due to an assebmly mismatch", fileName);
+ debugLog.Warn("No plugin instances were exposed via {asm} assembly. This may be due to an assebmly mismatch", fileName);
}
}
catch (Exception ex)
@@ -117,9 +129,6 @@ namespace VNLib.Plugins.Essentials.ServiceStack
//Remove the plugin from the table
_managedPlugins.Remove(plugin.Controller);
-
- //Dispose the plugin
- plugin.Dispose();
}
}
@@ -191,12 +200,25 @@ namespace VNLib.Plugins.Essentials.ServiceStack
//Dispose all managed plugins and clear the table
_managedPlugins.TryForeach(p => p.Value.Dispose());
_managedPlugins.Clear();
+
+ //Dispose the plugin stack
+ _stack.Dispose();
}
+ /*
+ * When using a service stack an loading manually, plugins that have errors
+ * will not be captured by this instance. However when using the shortcut
+ * extensions, the events will be invoked regaldess if we loaded the plugin
+ * here.
+ */
+
void IPluginEventListener.OnPluginLoaded(PluginController controller, object? state)
{
- //Handle service events
- ManagedPlugin mp = _managedPlugins.GetValue(controller, (pc) => null!);
+ //Make sure the plugin is managed by this manager
+ if(!_managedPlugins.TryGetValue(controller, out ManagedPlugin? mp))
+ {
+ return;
+ }
//Run onload method before invoking other handlers
mp.OnPluginLoaded();
@@ -210,8 +232,11 @@ namespace VNLib.Plugins.Essentials.ServiceStack
void IPluginEventListener.OnPluginUnloaded(PluginController controller, object? state)
{
- //Handle service events
- ManagedPlugin mp = _managedPlugins.GetValue(controller, (pc) => null!);
+ //Make sure the plugin is managed by this manager
+ if (!_managedPlugins.TryGetValue(controller, out ManagedPlugin? mp))
+ {
+ return;
+ }
//Run onload method before invoking other handlers
mp.OnPluginUnloaded();