aboutsummaryrefslogtreecommitdiff
path: root/lib/Plugins.Essentials.ServiceStack
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Plugins.Essentials.ServiceStack')
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/HttpServiceStackBuilder.cs28
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/IServiceHost.cs2
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs3
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs51
4 files changed, 65 insertions, 19 deletions
diff --git a/lib/Plugins.Essentials.ServiceStack/src/HttpServiceStackBuilder.cs b/lib/Plugins.Essentials.ServiceStack/src/HttpServiceStackBuilder.cs
index 5997cf9..95c6878 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/HttpServiceStackBuilder.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/HttpServiceStackBuilder.cs
@@ -23,6 +23,7 @@
*/
using System;
+using System.Linq;
using System.Collections.Generic;
using VNLib.Net.Http;
@@ -36,6 +37,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
/// </summary>
public sealed class HttpServiceStackBuilder
{
+
/// <summary>
/// Initializes a new <see cref="HttpServiceStack"/> that will
/// generate servers to listen for services exposed by the
@@ -54,7 +56,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
/// </summary>
/// <param name="hostBuilder">The callback method to build virtual hosts</param>
/// <returns>The current instance for chaining</returns>
- public HttpServiceStackBuilder WithDomainBuilder(Action<ICollection<IServiceHost>> hostBuilder)
+ public HttpServiceStackBuilder WithDomain(Action<ICollection<IServiceHost>> hostBuilder)
{
_hostBuilder = hostBuilder;
return this;
@@ -83,7 +85,29 @@ namespace VNLib.Plugins.Essentials.ServiceStack
}
/// <summary>
- /// Builds the new <see cref="HttpServiceStack"/> from the configured callbacks, WITHOUT loading plugins
+ /// Configures the stack to use the built-in http server implementation
+ /// </summary>
+ /// <param name="transport">The transport builder callback function</param>
+ /// <param name="config">The http configuration structure used to initalize servers</param>
+ /// <returns>The current instance for chaining</returns>
+ public HttpServiceStackBuilder WithBuiltInHttp(Func<ServiceGroup, ITransportProvider> transport, HttpConfig config)
+ {
+ return WithHttp(sg => new HttpServer(config, transport(sg), sg.Hosts.Select(static p => p.Processor)));
+ }
+
+ /// <summary>
+ /// Configures the stack to use the built-in http server implementation
+ /// </summary>
+ /// <param name="transport">The transport builder callback function</param>
+ /// <param name="configCallback">The http configuration builder callback method</param>
+ /// <returns>The current instance for chaining</returns>
+ public HttpServiceStackBuilder WithBuiltInHttp(Func<ServiceGroup, ITransportProvider> transport, Func<ServiceGroup, HttpConfig> configCallback)
+ {
+ return WithHttp(sg => new HttpServer(configCallback(sg), transport(sg), sg.Hosts.Select(static p => p.Processor)));
+ }
+
+ /// <summary>
+ /// Builds the new <see cref="HttpServiceStack"/> from the configured callbacks
/// </summary>
/// <returns>The newly constructed <see cref="HttpServiceStack"/> that may be used to manage your http services</returns>
/// <exception cref="ArgumentNullException"></exception>
diff --git a/lib/Plugins.Essentials.ServiceStack/src/IServiceHost.cs b/lib/Plugins.Essentials.ServiceStack/src/IServiceHost.cs
index 5d8fbe7..2517d66 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/IServiceHost.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/IServiceHost.cs
@@ -40,7 +40,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
IWebRoot Processor { get; }
/// <summary>
- /// The host's transport infomration
+ /// The host's transport information
/// </summary>
IHostTransportInfo TransportInfo { get; }
diff --git a/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs b/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
index 0fe4c93..429a465 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
@@ -112,9 +112,6 @@ namespace VNLib.Plugins.Essentials.ServiceStack
{
//Dispose services
_services?.Dispose();
-
- //Dispose loader
- Plugin.Dispose();
}
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();