From 107f9774df2ad484f3edc5f401c738f647f00f01 Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 6 Jan 2024 18:02:33 -0500 Subject: proj updates, interval deprecation & convert routes to services --- .../Events/ConfigurableAsyncIntervalAttribute.cs | 1 + .../src/Events/EventManagment.cs | 5 +- .../src/LoadingExtensions.cs | 6 +- .../src/RoutingExtensions.cs | 139 +-------------------- 4 files changed, 12 insertions(+), 139 deletions(-) (limited to 'lib/VNLib.Plugins.Extensions.Loading') diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Events/ConfigurableAsyncIntervalAttribute.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Events/ConfigurableAsyncIntervalAttribute.cs index 171a9ae..be8c16b 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/Events/ConfigurableAsyncIntervalAttribute.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Events/ConfigurableAsyncIntervalAttribute.cs @@ -30,6 +30,7 @@ namespace VNLib.Plugins.Extensions.Loading.Events /// When added to a method schedules it as a callback on a specified interval when /// the plugin is loaded, and stops when unloaded /// + [Obsolete("Depricated in favor of more verbose IIntervaleSchedulable apis")] [AttributeUsage(AttributeTargets.Method)] public sealed class ConfigurableAsyncIntervalAttribute : Attribute { diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs index 40a52fc..8b2ab40 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Extensions.Loading @@ -43,7 +43,8 @@ namespace VNLib.Plugins.Extensions.Loading.Events /// Provides event schedueling extensions for plugins /// public static class EventManagment - { + { + /// /// Schedules an asynchronous event interval for the current plugin, that is active until canceled or until the plugin unloads /// diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs index 979ade2..470d954 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs @@ -663,7 +663,7 @@ namespace VNLib.Plugins.Extensions.Loading } //Get the constructor for required or available config - constructor = serviceType.GetConstructor(new Type[] { typeof(PluginBase), typeof(IConfigScope) }); + constructor = serviceType.GetConstructor([typeof(PluginBase), typeof(IConfigScope)]); //Make sure the constructor exists _ = constructor ?? throw new MissingMemberException($"No constructor found for {serviceType.Name}"); @@ -671,13 +671,13 @@ namespace VNLib.Plugins.Extensions.Loading //Call constructore service = constructor.Invoke(new object[2] { plugin, config }); } - else if((constructor = serviceType.GetConstructor(new Type[] { typeof(PluginBase) })) != null) + else if((constructor = serviceType.GetConstructor([typeof(PluginBase)])) != null) { //Call constructor service = constructor.Invoke(new object[1] { plugin }); } //try to get empty constructor - else if ((constructor = serviceType.GetConstructor(Array.Empty())) != null) + else if ((constructor = serviceType.GetConstructor([])) != null) { //Invoked empty constructor service = constructor.Invoke(null); diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/RoutingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/RoutingExtensions.cs index c0f39d7..a1817a8 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/RoutingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/RoutingExtensions.cs @@ -23,13 +23,11 @@ */ using System; -using System.Linq; using System.Reflection; using System.Collections.Generic; using System.Runtime.CompilerServices; using VNLib.Plugins.Essentials.Runtime; -using VNLib.Plugins.Extensions.Loading.Events; namespace VNLib.Plugins.Extensions.Loading.Routing { @@ -47,74 +45,11 @@ namespace VNLib.Plugins.Extensions.Loading.Routing /// /// The type /// - /// If true, requires the configuration exist in the config file - /// The path to the plugin sepcific configuration property /// - public static T Route(this PluginBase plugin, string? pluginConfigPathName, bool configRequired = true) where T : IEndpoint + public static T Route(this PluginBase plugin) where T : IEndpoint { - Type endpointType = typeof(T); - - T endpoint; - try - { - //If the config attribute is not set, then ignore the config variables - if (string.IsNullOrWhiteSpace(pluginConfigPathName)) - { - ConstructorInfo? constructor = endpointType.GetConstructor(new Type[] { typeof(PluginBase) }); - - _ = constructor ?? throw new EntryPointNotFoundException($"No constructor t(PluginBase p) found for {endpointType.Name}"); - - //Create the new endpoint and pass the plugin instance - endpoint = (T)constructor.Invoke(new object[] { plugin }); - - //Register event handlers for the endpoint - ScheduleIntervals(plugin, endpoint, endpointType, null); - } - else - { - //Try to get config but allow null if not required - IConfigScope? config = plugin.TryGetConfig(pluginConfigPathName); - - if (configRequired && config == null) - { - ConfigurationExtensions.ThrowConfigNotFoundForType(endpointType); - return default; - } - - //Choose constructor based on config - if (config != null) - { - ConstructorInfo? constructor = endpointType.GetConstructor(new Type[] { typeof(PluginBase), typeof(IConfigScope) }); - - //Make sure the constructor exists - _ = constructor ?? throw new EntryPointNotFoundException($"No constructor t(PluginBase p, IConfigScope cs) found for {endpointType.Name}"); - - //Create the new endpoint and pass the plugin instance along with the configuration object - endpoint = (T)constructor.Invoke(new object[] { plugin, config }); - - //Register event handlers for the endpoint - ScheduleIntervals(plugin, endpoint, endpointType, config); - } - else - { - //Config does not exist, so use the default constructor - ConstructorInfo? constructor = endpointType.GetConstructor(new Type[] { typeof(PluginBase) }); - - _ = constructor ?? throw new EntryPointNotFoundException($"No constructor t(PluginBase p) found for {endpointType.Name}"); - - //Create the new endpoint and pass the plugin instance - endpoint = (T)constructor.Invoke(new object[] { plugin }); - - //Register event handlers for the endpoint - ScheduleIntervals(plugin, endpoint, endpointType, null); - } - } - } - catch(TargetInvocationException te) - { - LoadingExtensions.FindAndThrowInnerException(te); - throw; - } + //Create the endpoint service, then route it + T endpoint = plugin.CreateService(); //Route the endpoint plugin.Route(endpoint); @@ -122,31 +57,9 @@ namespace VNLib.Plugins.Extensions.Loading.Routing //Store ref to plugin for endpoint _pluginRefs.Add(endpoint, plugin); - //See if the endpoint is disposable - if (endpoint is IDisposable dis) - { - //Register dispose for unload - _ = plugin.RegisterForUnload(dis.Dispose); - } - return endpoint; } - /// - /// Constructs and routes the specific endpoint type for the current plugin - /// - /// The type - /// - /// - public static T Route(this PluginBase plugin) where T : IEndpoint - { - Type endpointType = typeof(T); - //Get config name attribute - ConfigurationNameAttribute? configAttr = endpointType.GetCustomAttribute(); - //Route using attribute - return plugin.Route(configAttr?.ConfigVarName, configAttr?.Required == true); - } - /// /// Routes a single endpoint for the current plugin and exports the collection to the /// service pool @@ -183,50 +96,8 @@ namespace VNLib.Plugins.Extensions.Loading.Routing { _ = _pluginRefs.TryGetValue(ep, out PluginBase? pBase); return pBase ?? throw new InvalidOperationException("Endpoint was not dynamically routed"); - } - - private static void ScheduleIntervals(PluginBase plugin, T endpointInstance, Type epType, IConfigScope? endpointLocalConfig) where T : IEndpoint - { - //Get all methods that have the configurable async interval attribute specified - IEnumerable> confIntervals = epType.GetMethods() - .Where(m => m.GetCustomAttribute() != null) - .Select(m => new Tuple - (m.GetCustomAttribute()!, m.CreateDelegate(endpointInstance))); - - //If the endpoint has a local config, then use it to find the interval - if (endpointLocalConfig != null) - { - - //Schedule event handlers on the current plugin - foreach (Tuple interval in confIntervals) - { - int value = endpointLocalConfig[interval.Item1.IntervalPropertyName].GetInt32(); - //Get the timeout from its resolution variable - TimeSpan timeout = interval.Item1.Resolution switch - { - IntervalResultionType.Seconds => TimeSpan.FromSeconds(value), - IntervalResultionType.Minutes => TimeSpan.FromMinutes(value), - IntervalResultionType.Hours => TimeSpan.FromHours(value), - _ => TimeSpan.FromMilliseconds(value), - }; - //Schedule - plugin.ScheduleInterval(interval.Item2, timeout); - } - } - - //Get all methods that have the async interval attribute specified - IEnumerable> intervals = epType.GetMethods() - .Where(m => m.GetCustomAttribute() != null) - .Select(m => new Tuple( - m.GetCustomAttribute()!, m.CreateDelegate(endpointInstance)) - ); - - //Schedule event handlers on the current plugin - foreach (Tuple interval in intervals) - { - plugin.ScheduleInterval(interval.Item2, interval.Item1.Interval); - } - } + } + private sealed class EndpointCollection : IVirtualEndpointDefinition { -- cgit