aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Net.Rest.Client/src/OAuth2/O2ErrorResponseMessage.cs4
-rw-r--r--lib/Net.Rest.Client/src/OAuth2/OAuth2AuthenticationException.cs2
-rw-r--r--lib/Net.Rest.Client/src/OAuth2/OAuth2Authenticator.cs7
-rw-r--r--lib/Net.Rest.Client/src/RestClientPool.cs2
-rw-r--r--lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj3
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs25
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/PluginLoadConfiguration.cs9
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs35
-rw-r--r--lib/Plugins.PluginBase/src/PluginBase.cs57
-rw-r--r--lib/Plugins.Runtime/src/RuntimePluginLoader.cs31
10 files changed, 95 insertions, 80 deletions
diff --git a/lib/Net.Rest.Client/src/OAuth2/O2ErrorResponseMessage.cs b/lib/Net.Rest.Client/src/OAuth2/O2ErrorResponseMessage.cs
index 151c575..f2ffbaa 100644
--- a/lib/Net.Rest.Client/src/OAuth2/O2ErrorResponseMessage.cs
+++ b/lib/Net.Rest.Client/src/OAuth2/O2ErrorResponseMessage.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Rest.Client
@@ -56,7 +56,7 @@ namespace VNLib.Net.Rest.Client.OAuth2
/// <param name="description">The OAuth2 error description</param>
public O2ErrorResponseMessage(string code, string description)
{
- this.ErrorCode = code;
+ ErrorCode = code;
ErrorDescription = description;
}
diff --git a/lib/Net.Rest.Client/src/OAuth2/OAuth2AuthenticationException.cs b/lib/Net.Rest.Client/src/OAuth2/OAuth2AuthenticationException.cs
index 7176093..96242f2 100644
--- a/lib/Net.Rest.Client/src/OAuth2/OAuth2AuthenticationException.cs
+++ b/lib/Net.Rest.Client/src/OAuth2/OAuth2AuthenticationException.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Rest.Client
diff --git a/lib/Net.Rest.Client/src/OAuth2/OAuth2Authenticator.cs b/lib/Net.Rest.Client/src/OAuth2/OAuth2Authenticator.cs
index b978404..61af299 100644
--- a/lib/Net.Rest.Client/src/OAuth2/OAuth2Authenticator.cs
+++ b/lib/Net.Rest.Client/src/OAuth2/OAuth2Authenticator.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Rest.Client
@@ -23,7 +23,6 @@
*/
using System;
-using System.Net;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -34,8 +33,6 @@ using RestSharp.Authenticators;
using VNLib.Utils;
using VNLib.Utils.Extensions;
-#nullable enable
-
namespace VNLib.Net.Rest.Client.OAuth2
{
/// <summary>
@@ -72,7 +69,7 @@ namespace VNLib.Net.Rest.Client.OAuth2
_tokenLock = new(1, 1);
}
- async ValueTask IAuthenticator.Authenticate(RestClient client, RestRequest request)
+ async ValueTask IAuthenticator.Authenticate(IRestClient client, RestRequest request)
{
//Wait for access to the token incase another thread is updating it
using SemSlimReleaser releaser = await _tokenLock.GetReleaserAsync(CancellationToken.None);
diff --git a/lib/Net.Rest.Client/src/RestClientPool.cs b/lib/Net.Rest.Client/src/RestClientPool.cs
index 2d61203..5c3d401 100644
--- a/lib/Net.Rest.Client/src/RestClientPool.cs
+++ b/lib/Net.Rest.Client/src/RestClientPool.cs
@@ -29,8 +29,6 @@ using RestSharp.Authenticators;
using VNLib.Utils.Memory.Caching;
-#nullable enable
-
namespace VNLib.Net.Rest.Client
{
/// <summary>
diff --git a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
index d25a307..b6b2bd5 100644
--- a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
+++ b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
+ <Nullable>enable</Nullable>
<AssemblyName>VNLib.Net.Rest.Client</AssemblyName>
<RootNamespace>VNLib.Net.Rest.Client</RootNamespace>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
@@ -41,7 +42,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
- <PackageReference Include="RestSharp" Version="109.0.1" />
+ <PackageReference Include="RestSharp" Version="110.2.0" />
</ItemGroup>
<ItemGroup>
diff --git a/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs b/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
index 596ea83..3bf99cb 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/ManagedPlugin.cs
@@ -27,13 +27,17 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Reflection;
+using System.Runtime.Loader;
using System.Threading.Tasks;
using System.ComponentModel.Design;
+using McMaster.NETCore.Plugins;
+
using VNLib.Utils;
using VNLib.Plugins.Runtime;
using VNLib.Plugins.Attributes;
+
namespace VNLib.Plugins.Essentials.ServiceStack
{
@@ -44,12 +48,15 @@ namespace VNLib.Plugins.Essentials.ServiceStack
private UnloadableServiceContainer? _services;
- public ManagedPlugin(string pluginPath, PluginLoadConfiguration config, IPluginEventListener listener)
+ public ManagedPlugin(string pluginPath, in PluginLoadConfiguration config, IPluginEventListener listener)
{
PluginPath = pluginPath;
+ //Get the plugin config for the assembly
+ PluginConfig pConfig = GetConfigForAssemblyPath(pluginPath, in config);
+
//configure the loader
- _plugin = new(pluginPath, config.HostConfig, config.PluginErrorLog, config.HotReload, config.HotReload);
+ _plugin = new(pConfig, config.HostConfig, config.PluginErrorLog);
//Register listener before loading occurs
_plugin.Controller.Register(this, this);
@@ -58,6 +65,20 @@ namespace VNLib.Plugins.Essentials.ServiceStack
_serviceDomainListener = listener;
}
+ private static PluginConfig GetConfigForAssemblyPath(string asmPath, in PluginLoadConfiguration loadConfig)
+ {
+ PluginConfig config = new(asmPath)
+ {
+ IsUnloadable = loadConfig.HotReload,
+ EnableHotReload = loadConfig.HotReload,
+ IsLazyLoaded = false,
+ PreferSharedTypes = true,
+ DefaultContext = AssemblyLoadContext.Default,
+ ReloadDelay = loadConfig.ReloadDelay
+ };
+ return config;
+ }
+
///<inheritdoc/>
public string PluginPath { get; }
diff --git a/lib/Plugins.Essentials.ServiceStack/src/PluginLoadConfiguration.cs b/lib/Plugins.Essentials.ServiceStack/src/PluginLoadConfiguration.cs
index 73cb201..894ae55 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/PluginLoadConfiguration.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/PluginLoadConfiguration.cs
@@ -22,13 +22,12 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
-
+using System;
using System.Text.Json;
using VNLib.Utils.Logging;
using VNLib.Plugins.Runtime;
-
namespace VNLib.Plugins.Essentials.ServiceStack
{
/// <summary>
@@ -58,5 +57,11 @@ namespace VNLib.Plugins.Essentials.ServiceStack
/// holding plugins
/// </summary>
public readonly ILogProvider? PluginErrorLog { get; init; }
+
+ /// <summary>
+ /// If hot-reload is enabled, sets a time delay the file watcher waits when
+ /// a plugin assembly has changed.
+ /// </summary>
+ public readonly TimeSpan ReloadDelay { get; init; }
}
}
diff --git a/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs b/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
index cdcf7ba..e4e5670 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
+++ b/lib/Plugins.Essentials.ServiceStack/src/PluginManager.cs
@@ -134,12 +134,7 @@ namespace VNLib.Plugins.Essentials.ServiceStack
private async Task InitializePlugin(ManagedPlugin plugin, ILogProvider debugLog)
{
- try
- {
- //Load wrapper
- await plugin.InitializePluginsAsync().ConfigureAwait(true);
- }
- catch (Exception ex)
+ void LogAndRemovePlugin(Exception ex)
{
debugLog.Error(ex, $"Exception raised during initialzation of {plugin.PluginFileName}. It has been removed from the collection\n{ex}");
@@ -152,6 +147,20 @@ namespace VNLib.Plugins.Essentials.ServiceStack
//Dispose the plugin
plugin.Dispose();
}
+
+ try
+ {
+ //Load wrapper
+ await plugin.InitializePluginsAsync().ConfigureAwait(true);
+ }
+ catch(AggregateException ae) when (ae.InnerException != null)
+ {
+ LogAndRemovePlugin(ae.InnerException);
+ }
+ catch (Exception ex)
+ {
+ LogAndRemovePlugin(ex);
+ }
}
private static void LoadPlugin(ManagedPlugin plugin, ILogProvider debugLog)
@@ -166,7 +175,19 @@ namespace VNLib.Plugins.Essentials.ServiceStack
sw.Stop();
- debugLog.Verbose("Loaded {pl} in {tm} ms", plugin.PluginFileName, sw.ElapsedMilliseconds);
+ /*
+ * If the plugin assembly does not expose any plugin types or there is an issue loading the assembly,
+ * its types my not unify, then we should give the user feedback insead of a silent fail.
+ */
+ if (!plugin.Controller.Plugins.Any())
+ {
+ debugLog.Warn("No plugin instances were exposed via {ams} assembly. This may be due to an assebmly mismatch", plugin.PluginFileName);
+ }
+ else
+ {
+ debugLog.Verbose("Loaded {pl} in {tm} ms", plugin.PluginFileName, sw.ElapsedMilliseconds);
+ }
+
}
catch (Exception ex)
{
diff --git a/lib/Plugins.PluginBase/src/PluginBase.cs b/lib/Plugins.PluginBase/src/PluginBase.cs
index a291e77..80860e7 100644
--- a/lib/Plugins.PluginBase/src/PluginBase.cs
+++ b/lib/Plugins.PluginBase/src/PluginBase.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.PluginBase
@@ -69,22 +69,27 @@ namespace VNLib.Plugins
/// by the host app
/// </summary>
public ICollection<IEndpoint> Endpoints { get; } = new List<IEndpoint>();
+
/// <summary>
/// The logging instance
/// </summary>
public ILogProvider Log { get; private set; }
+
/// <summary>
/// If passed by the host application, the configuration file of the host application and plugin
/// </summary>
protected JsonDocument Configuration { get; private set; }
+
/// <summary>
/// The configuration data from the host application
/// </summary>
- public JsonElement HostConfig { get; private set; }
+ public JsonElement HostConfig => Configuration.RootElement.GetProperty(GlobalConfigDomPropertyName);
+
/// <summary>
/// The configuration data from the plugin's config file passed by the host application
/// </summary>
- public JsonElement PluginConfig { get; private set; }
+ public JsonElement PluginConfig => Configuration.RootElement.GetProperty(GetType().Name);
+
/// <summary>
/// <inheritdoc/>
/// </summary>
@@ -105,10 +110,6 @@ namespace VNLib.Plugins
_ = config ?? throw new ArgumentNullException(nameof(config));
//Store config ref to dispose properly
Configuration = config;
- //Load congfiguration elements
- HostConfig = config.RootElement.GetProperty(GlobalConfigDomPropertyName);
- //Plugin config propery name is the name of the current type
- PluginConfig = config.RootElement.GetProperty(this.GetType().Name);
}
/// <summary>
@@ -154,7 +155,7 @@ namespace VNLib.Plugins
//If silent arg is not specified, open log to console
if (!(args.Contains("--silent") || args.Contains("-s")))
{
- logConfig.WriteTo.Console(outputTemplate: LogTemplate);
+ _ = logConfig.WriteTo.Console(outputTemplate: LogTemplate, formatProvider:null);
}
}
@@ -170,7 +171,7 @@ namespace VNLib.Plugins
int fileSizeLimit = 500 * 1000 * 1024;
RollingInterval interval = RollingInterval.Infinite;
- //try to get the host's app_log config object
+ //try to get the host's app_log config object, if it does not exist, do not write logs to file
if (HostConfig.TryGetProperty("app_log", out JsonElement logEl))
{
IReadOnlyDictionary<string, JsonElement> conf = logEl.EnumerateObject().ToDictionary(static s => s.Name, static s => s.Value);
@@ -206,20 +207,21 @@ namespace VNLib.Plugins
//Replace the file name
filePath = filePath.Replace(appLogName, PluginName, StringComparison.Ordinal);
}
- }
- //Default if not set
- filePath ??= Path.Combine(Environment.CurrentDirectory, $"{PluginName}.txt");
- template ??= LogTemplate;
-
- //Configure the log file writer
- logConfig.WriteTo.File(filePath,
- buffered: true,
- retainedFileCountLimit: retainedLogs,
- fileSizeLimitBytes: fileSizeLimit,
- rollingInterval: interval,
- outputTemplate: template,
- flushToDiskInterval: flushInterval);
+ //Default to exe dir if not set
+ filePath ??= Path.Combine(Environment.CurrentDirectory, $"{PluginName}.txt");
+ template ??= LogTemplate;
+
+ //Configure the log file writer
+ logConfig.WriteTo.File(filePath,
+ buffered: true,
+ retainedFileCountLimit: retainedLogs,
+ formatProvider: null,
+ fileSizeLimitBytes: fileSizeLimit,
+ rollingInterval: interval,
+ outputTemplate: template,
+ flushToDiskInterval: flushInterval);
+ }
}
/// <summary>
@@ -356,6 +358,12 @@ namespace VNLib.Plugins
}
/// <summary>
+ /// Adds the specified endpoint to be routed when loading is complete
+ /// </summary>
+ /// <param name="endpoint">The <see cref="IEndpoint"/> to present to the application when loaded</param>
+ public void Route(IEndpoint endpoint) => Endpoints.Add(endpoint);
+
+ /// <summary>
/// <para>
/// Invoked when the host loads the plugin instance
/// </para>
@@ -373,10 +381,5 @@ namespace VNLib.Plugins
/// for the current plugin
/// </summary>
protected virtual void OnGetEndpoints() { }
- /// <summary>
- /// Adds the specified endpoint to be routed when loading is complete
- /// </summary>
- /// <param name="endpoint">The <see cref="IEndpoint"/> to present to the application when loaded</param>
- public void Route(IEndpoint endpoint) => Endpoints.Add(endpoint);
}
} \ No newline at end of file
diff --git a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
index 2a03a3d..83aad21 100644
--- a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
+++ b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs
@@ -26,7 +26,6 @@ using System;
using System.IO;
using System.Text.Json;
using System.Reflection;
-using System.Runtime.Loader;
using System.Threading.Tasks;
using McMaster.NETCore.Plugins;
@@ -59,33 +58,6 @@ namespace VNLib.Plugins.Runtime
public string PluginConfigPath { get; }
/// <summary>
- /// Creates a new <see cref="RuntimePluginLoader"/> with the specified
- /// assembly location and host config.
- /// </summary>
- /// <param name="pluginPath"></param>
- /// <param name="log">A nullable log provider</param>
- /// <param name="hostConfig">The configuration DOM to merge with plugin config DOM and pass to enabled plugins</param>
- /// <param name="unloadable">A value that specifies if the assembly can be unloaded</param>
- /// <param name="hotReload">A value that spcifies if the loader will listen for changes to the assembly file and reload the plugins</param>
- /// <remarks>
- /// The <paramref name="log"/> argument may be null if <paramref name="unloadable"/> is false
- /// </remarks>
- /// <exception cref="ArgumentNullException"></exception>
- public RuntimePluginLoader(string pluginPath, JsonElement? hostConfig = null, ILogProvider? log = null, bool unloadable = false, bool hotReload = false)
- :this(
- new PluginConfig(pluginPath)
- {
- IsUnloadable = unloadable || hotReload,
- EnableHotReload = hotReload,
- ReloadDelay = TimeSpan.FromSeconds(1),
- PreferSharedTypes = true,
- DefaultContext = AssemblyLoadContext.Default
- },
- hostConfig, log)
- {
- }
-
- /// <summary>
/// Creates a new <see cref="RuntimePluginLoader"/> with the specified config and host config dom.
/// </summary>
/// <param name="config">The plugin's loader configuration </param>
@@ -94,9 +66,6 @@ namespace VNLib.Plugins.Runtime
/// <exception cref="ArgumentNullException"></exception>
public RuntimePluginLoader(PluginConfig config, JsonElement? hostConfig, ILogProvider? log)
{
- //Shared types is required so the default load context shares types
- config.PreferSharedTypes = true;
-
//Default to empty config if null, otherwise clone a copy of the host config element
HostConfig = hostConfig.HasValue ? Clone(hostConfig.Value) : JsonDocument.Parse("{}");