diff options
author | vman <public@vaughnnugent.com> | 2022-10-30 02:28:12 -0400 |
---|---|---|
committer | vman <public@vaughnnugent.com> | 2022-10-30 02:28:12 -0400 |
commit | a8510fb835dcc5e1142d700164ce5a4bd44e1a25 (patch) | |
tree | 28caab320f777a384cb6883b68dd999cdc8c0a3f /Plugins/SessionProvider |
Add project files.
Diffstat (limited to 'Plugins/SessionProvider')
-rw-r--r-- | Plugins/SessionProvider/GlobalCache.cs | 141 | ||||
-rw-r--r-- | Plugins/SessionProvider/LocalizedLogProvider.cs | 48 | ||||
-rw-r--r-- | Plugins/SessionProvider/SessionClientEntryPoint.cs | 123 | ||||
-rw-r--r-- | Plugins/SessionProvider/SessionProvider.csproj | 56 |
4 files changed, 368 insertions, 0 deletions
diff --git a/Plugins/SessionProvider/GlobalCache.cs b/Plugins/SessionProvider/GlobalCache.cs new file mode 100644 index 0000000..ff16f47 --- /dev/null +++ b/Plugins/SessionProvider/GlobalCache.cs @@ -0,0 +1,141 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +//using VNLib.Data.Caching; +//using VNLib.Net.Messaging.FBM.Client; +//using VNLib.Net.Messaging.FBM.Client.Exceptions; + + +namespace VNLib.Plugins.Essentials.Sessions +{ + /*internal class GlobalCache : IGlobalCacheProvider + { + private readonly FBMClient Client; + private readonly TimeSpan OperationTimeout; + + public GlobalCache(FBMClient cacheProvider, TimeSpan cancellation) + { + this.Client = cacheProvider; + this.OperationTimeout = cancellation; + } + + //If the wait handle will block, the client is connected + bool IGlobalCacheProvider.IsConnected => !Client.ConnectionStatusHandle.WaitOne(0); + + async Task IGlobalCacheProvider.DeleteAsync(string key) + { + if (OperationTimeout > TimeSpan.Zero && OperationTimeout < TimeSpan.MaxValue) + { + CancellationTokenSource cts = new(OperationTimeout); + try + { + //Delete value + await Client.DeleteObjectAsync(key, cts.Token); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + catch (OperationCanceledException) + { + throw new TimeoutException("The operation has been cancelled, due to a timeout"); + } + finally + { + cts.Dispose(); + } + } + else + { + try + { + //Delete value + await Client.DeleteObjectAsync(key); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + } + } + + async Task<T> IGlobalCacheProvider.GetAsync<T>(string key) + { + if (OperationTimeout > TimeSpan.Zero && OperationTimeout < TimeSpan.MaxValue) + { + CancellationTokenSource cts = new(OperationTimeout); + try + { + //Try to get the value + return await Client.GetObjectAsync<T>(key, cts.Token); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + catch (OperationCanceledException) + { + throw new TimeoutException("The operation has been cancelled, due to a timeout"); + } + finally + { + cts.Dispose(); + } + } + else + { + try + { + //Try to get the value + return await Client.GetObjectAsync<T>(key); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + } + } + + async Task IGlobalCacheProvider.SetAsync<T>(string key, T value) + { + if (OperationTimeout > TimeSpan.Zero && OperationTimeout < TimeSpan.MaxValue) + { + CancellationTokenSource cts = new(OperationTimeout); + try + { + await Client.AddOrUpdateObjectAsync(key, null, value, cts.Token); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + catch (OperationCanceledException) + { + throw new TimeoutException("The operation has been cancelled, due to a timeout"); + } + finally + { + cts.Dispose(); + } + } + else + { + try + { + await Client.AddOrUpdateObjectAsync(key, null, value); + } + catch (FBMException fbm) + { + //Catch fbm excpetions and wrap them in global cache exception + throw new GlobalCacheException("Failed to delete cache record, see inner exception", fbm); + } + } + } + }*/ +} diff --git a/Plugins/SessionProvider/LocalizedLogProvider.cs b/Plugins/SessionProvider/LocalizedLogProvider.cs new file mode 100644 index 0000000..2bd9bc4 --- /dev/null +++ b/Plugins/SessionProvider/LocalizedLogProvider.cs @@ -0,0 +1,48 @@ +using System; + +using VNLib.Utils.Logging; + +namespace VNLib.Plugins.Essentials.Sessions +{ + internal sealed class LocalizedLogProvider : ILogProvider + { + private readonly ILogProvider Log; + private readonly string LogPrefix; + + public LocalizedLogProvider(ILogProvider log, string prefix) + { + Log = log; + LogPrefix = prefix; + } + + public void Flush() + { + Log.Flush(); + } + + public object GetLogProvider() + { + return Log.GetLogProvider(); + } + + public void Write(LogLevel level, string value) + { + Log.Write(level, $"[{LogPrefix}]: {value}"); + } + + public void Write(LogLevel level, Exception exception, string value = "") + { + Log.Write(level, exception, $"[{LogPrefix}]: {value}"); + } + + public void Write(LogLevel level, string value, params object[] args) + { + Log.Write(level, $"[{LogPrefix}]: {value}", args); + } + + public void Write(LogLevel level, string value, params ValueType[] args) + { + Log.Write(level, $"[{LogPrefix}]: {value}", args); + } + } +} diff --git a/Plugins/SessionProvider/SessionClientEntryPoint.cs b/Plugins/SessionProvider/SessionClientEntryPoint.cs new file mode 100644 index 0000000..07be1ef --- /dev/null +++ b/Plugins/SessionProvider/SessionClientEntryPoint.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; + +using VNLib.Net.Http; +using VNLib.Utils.Logging; +using VNLib.Plugins.Extensions.Loading; + +namespace VNLib.Plugins.Essentials.Sessions +{ + /// <summary> + /// The implementation type for dynamic loading of unified session providers + /// </summary> + public sealed class SessionClientEntryPoint : PluginBase, ISessionProvider + { + public override string PluginName => "Essentials.Sessions"; + + + private readonly List<AssemblyLoader<IRuntimeSessionProvider>> ProviderLoaders = new(); + + private IRuntimeSessionProvider[] ProviderArray = Array.Empty<IRuntimeSessionProvider>(); + + + ValueTask<SessionHandle> ISessionProvider.GetSessionAsync(IHttpEvent entity, CancellationToken token) + { + //Loop through providers + for (int i = 0; i < ProviderArray.Length; i++) + { + //Check if provider can process the entity + if (ProviderArray[i].CanProcess(entity)) + { + //Get session + return ProviderArray[i].GetSessionAsync(entity, token); + } + } + + //Return empty session + return new ValueTask<SessionHandle>(SessionHandle.Empty); + } + + protected override void OnLoad() + { + try + { + Log.Verbose("Loading all specified session providers"); + + //Get all provider names + IEnumerable<string> providerAssemblyNames = PluginConfig.GetProperty("provider_assemblies") + .EnumerateArray() + .Where(s => s.GetString() != null) + .Select(s => s.GetString()!); + + + foreach(string asm in providerAssemblyNames) + { + Log.Verbose("Loading {dll} session provider", asm); + + //Attempt to load provider + AssemblyLoader<IRuntimeSessionProvider> prov = this.LoadAssembly<IRuntimeSessionProvider>(asm); + + //Create localized log + LocalizedLogProvider log = new(Log, $"{Path.GetFileName(asm)}"); + + //Try to load the websessions + prov.Resource.Load(this, log); + + //Add provider to list + ProviderLoaders.Add(prov); + } + + if(ProviderLoaders.Count > 0) + { + //Create array for searching for providers + ProviderArray = ProviderLoaders.Select(s => s.Resource).ToArray(); + + Log.Information("Loaded {count} session providers", ProviderArray.Length); + } + else + { + Log.Information("No session providers loaded"); + } + + Log.Information("Plugin loaded"); + } + catch (KeyNotFoundException knf) + { + //Dispose providers + ProviderLoaders.ForEach(s => s.Dispose()); + + Log.Warn("Plugin configuration was missing required variables {var}", knf.Message); + } + catch + { + //Dispose providers + ProviderLoaders.ForEach(s => s.Dispose()); + throw; + } + } + + protected override void OnUnLoad() + { + //Clear array + ProviderArray = Array.Empty<IRuntimeSessionProvider>(); + + //Cleanup assemblies + ProviderLoaders.ForEach(p => p.Dispose()); + ProviderLoaders.Clear(); + + Log.Information("Plugin unloaded"); + } + + protected override void ProcessHostCommand(string cmd) + { + if (!this.IsDebug()) + { + return; + } + } + } +} diff --git a/Plugins/SessionProvider/SessionProvider.csproj b/Plugins/SessionProvider/SessionProvider.csproj new file mode 100644 index 0000000..d20a524 --- /dev/null +++ b/Plugins/SessionProvider/SessionProvider.csproj @@ -0,0 +1,56 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <RootNamespace>VNLib.Plugins.Essentials.Sessions</RootNamespace> + <AssemblyName>SessionProvider</AssemblyName> + <PackageId>SessionProvider</PackageId> + <Authors>Vaughn Nugent</Authors> + <Product>SessionProvider</Product> + <Copyright>Copyright © 2022 Vaughn Nugent</Copyright> + <Version>1.0.3.1</Version> + <PackageProjectUrl>www.vaughnnugent.com/resources</PackageProjectUrl> + <Platforms>AnyCPU;x64</Platforms> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + </ItemGroup> + + <!-- Resolve nuget dll files and store them in the output dir --> + <PropertyGroup> + <EnableDynamicLoading>true</EnableDynamicLoading> + <AssemblyVersion>1.0.2.1</AssemblyVersion> + <FileVersion>1.0.2.1</FileVersion> + <Nullable>enable</Nullable> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> + <Deterministic>False</Deterministic> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Deterministic>False</Deterministic> + </PropertyGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\VNLib\Utils\src\VNLib.Utils.csproj" /> + <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading\VNLib.Plugins.Extensions.Loading.csproj" /> + <ProjectReference Include="..\..\Libs\VNLib.Plugins.Essentials.Sessions.Runtime\VNLib.Plugins.Essentials.Sessions.Runtime.csproj" /> + </ItemGroup> + + <ItemGroup> + <None Update="SessionProvider.json"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + </ItemGroup> + + <Target Name="PostBuild" AfterTargets="PostBuildEvent"> + <Exec Command="start xcopy "$(TargetDir)" "F:\Programming\Web Plugins\DevPlugins\$(TargetName)" /E /Y /R" /> + </Target> + +</Project> |