aboutsummaryrefslogtreecommitdiff
path: root/Plugins/SessionProvider
diff options
context:
space:
mode:
authorLibravatar vman <public@vaughnnugent.com>2022-10-30 02:28:12 -0400
committerLibravatar vman <public@vaughnnugent.com>2022-10-30 02:28:12 -0400
commita8510fb835dcc5e1142d700164ce5a4bd44e1a25 (patch)
tree28caab320f777a384cb6883b68dd999cdc8c0a3f /Plugins/SessionProvider
Add project files.
Diffstat (limited to 'Plugins/SessionProvider')
-rw-r--r--Plugins/SessionProvider/GlobalCache.cs141
-rw-r--r--Plugins/SessionProvider/LocalizedLogProvider.cs48
-rw-r--r--Plugins/SessionProvider/SessionClientEntryPoint.cs123
-rw-r--r--Plugins/SessionProvider/SessionProvider.csproj56
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 &quot;$(TargetDir)&quot; &quot;F:\Programming\Web Plugins\DevPlugins\$(TargetName)&quot; /E /Y /R" />
+ </Target>
+
+</Project>