aboutsummaryrefslogtreecommitdiff
path: root/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs')
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs34
1 files changed, 31 insertions, 3 deletions
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
index e76d7a4..1af885e 100644
--- a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
+++ b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
@@ -28,11 +28,12 @@ using System.Threading.Tasks;
using System.Collections.Generic;
using VNLib.Net.Http;
+using VNLib.Net.Http.Core;
using VNLib.Utils;
using VNLib.Utils.Async;
+using VNLib.Utils.Logging;
using VNLib.Utils.Extensions;
using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Net.Http.Core;
#nullable enable
@@ -47,12 +48,14 @@ namespace VNLib.Plugins.Essentials.Sessions.Memory
internal readonly MemorySessionConfig Config;
internal readonly SessionIdFactory IdFactory;
+ internal readonly AsyncQueue<MemorySession> ExpiredSessions;
public MemorySessionStore(MemorySessionConfig config)
{
Config = config;
SessionsStore = new(config.MaxAllowedSessions, StringComparer.Ordinal);
IdFactory = new(config.SessionIdSizeBytes, config.SessionCookieID, config.SessionTimeout);
+ ExpiredSessions = new(false, true);
}
///<inheritdoc/>
@@ -68,7 +71,7 @@ namespace VNLib.Plugins.Essentials.Sessions.Memory
if (IdFactory.TryGetSessionId(entity, out string? sessionId))
{
//Try to get the old record or evict it
- ERRNO result = SessionsStore.TryGetOrEvictRecord(sessionId, out MemorySession session);
+ ERRNO result = SessionsStore.TryGetOrEvictRecord(sessionId, out MemorySession? session);
if(result > 0)
{
//Valid, now wait for exclusive access
@@ -89,7 +92,7 @@ namespace VNLib.Plugins.Essentials.Sessions.Memory
return new(null, FileProcessArgs.VirtualSkip, null);
}
//Initialze a new session
- session = new(sessionId, entity.Server.GetTrustedIp(), UpdateSessionId);
+ session = new(sessionId, entity.Server.GetTrustedIp(), UpdateSessionId, ExpiredSessions);
//Increment the semaphore
(session as IWaitHandle).WaitOne();
//store the session in cache while holding semaphore, and set its expiration
@@ -104,6 +107,31 @@ namespace VNLib.Plugins.Essentials.Sessions.Memory
}
}
+ public async Task CleanupExiredAsync(ILogProvider log, CancellationToken token)
+ {
+ while (true)
+ {
+ try
+ {
+ //Wait for expired session and dispose it
+ using MemorySession session = await ExpiredSessions.DequeueAsync(token);
+
+ //Obtain lock on session
+ await session.WaitOneAsync(CancellationToken.None);
+
+ log.Verbose("Removed expired session {id}", session.SessionID);
+ }
+ catch (OperationCanceledException)
+ {
+ break;
+ }
+ catch (Exception ex)
+ {
+ log.Error(ex);
+ }
+ }
+ }
+
private string UpdateSessionId(IHttpEvent entity, string oldId)
{
//Generate and set a new sessionid