Skip to content

Commit 95c3ff7

Browse files
claudiamurialdoBeta Bot
authored andcommitted
Cherry pick branch 'genexuslabs:custom-redis-session-store' into beta
1 parent 18f5b87 commit 95c3ff7

File tree

2 files changed

+88
-22
lines changed

2 files changed

+88
-22
lines changed

dotnet/src/dotnetcore/GxNetCoreStartup/SessionHelper.cs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1-
using Microsoft.AspNetCore.Http;
2-
using Microsoft.Extensions.Caching.Distributed;
3-
using Microsoft.Extensions.Caching.StackExchangeRedis;
1+
using System;
42
using System.Collections.Concurrent;
5-
using System.Threading.Tasks;
3+
using System.Linq;
64
using System.Threading;
7-
using System;
5+
using System.Threading.Tasks;
86
using GeneXus.Services;
9-
using System.Linq;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.Extensions.Caching.Distributed;
9+
using StackExchange.Redis;
1010

1111
namespace GeneXus.Application
1212
{
1313
public class TenantRedisCache : IDistributedCache
1414
{
1515
private readonly IHttpContextAccessor _httpContextAccessor;
16-
private readonly IServiceProvider _serviceProvider;
17-
private readonly ConcurrentDictionary<string, RedisCache> _redisCaches = new();
16+
private readonly ConcurrentDictionary<string, IDistributedCache> _redisCaches = new();
1817

19-
public TenantRedisCache(IHttpContextAccessor httpContextAccessor, IServiceProvider serviceProvider)
18+
public TenantRedisCache(IHttpContextAccessor httpContextAccessor)
2019
{
2120
_httpContextAccessor = httpContextAccessor;
22-
_serviceProvider = serviceProvider;
2321
}
2422

2523
private IDistributedCache GetTenantCache()
@@ -29,12 +27,7 @@ private IDistributedCache GetTenantCache()
2927
return _redisCaches.GetOrAdd(tenantId, id =>
3028
{
3129
ISessionService sessionService = GXSessionServiceFactory.GetProvider();
32-
var options = new RedisCacheOptions
33-
{
34-
Configuration = sessionService.ConnectionString,
35-
InstanceName = $"{id}:"
36-
};
37-
return new RedisCache(options);
30+
return new CustomRedisSessionStore(sessionService.ConnectionString, TimeSpan.FromMinutes(sessionService.SessionTimeout), id);
3831
});
3932
}
4033

@@ -48,6 +41,80 @@ private IDistributedCache GetTenantCache()
4841
public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default) => GetTenantCache().SetAsync(key, value, options, token);
4942
}
5043

44+
public class CustomRedisSessionStore : IDistributedCache
45+
{
46+
private readonly IDatabase _db;
47+
private readonly TimeSpan _idleTimeout;
48+
private readonly TimeSpan _refreshThreshold;
49+
private readonly string _instanceName;
50+
51+
public CustomRedisSessionStore(string connectionString, TimeSpan idleTimeout, string instanceName)
52+
{
53+
var mux = ConnectionMultiplexer.Connect(connectionString);
54+
_db = mux.GetDatabase();
55+
_idleTimeout = idleTimeout;
56+
_refreshThreshold = TimeSpan.FromTicks((long)(idleTimeout.Ticks * 0.2));
57+
_instanceName = instanceName ?? string.Empty;
58+
}
59+
60+
private string FormatKey(string key) => string.IsNullOrEmpty(_instanceName) ? key : $"{_instanceName}:{key}";
61+
62+
public byte[] Get(string key) => _db.StringGet(FormatKey(key));
63+
64+
public async Task<byte[]> GetAsync(string key, CancellationToken token = default)
65+
{
66+
string redisKey = FormatKey(key);
67+
var value = await _db.StringGetAsync(redisKey);
68+
69+
await RefreshKeyIfNeededAsync(redisKey);
70+
71+
return value;
72+
}
73+
74+
public void Refresh(string key)
75+
{
76+
string redisKey = FormatKey(key);
77+
78+
var ttl = _db.KeyTimeToLive(redisKey);
79+
80+
if (ShouldRefreshKey(ttl))
81+
{
82+
_db.KeyExpire(redisKey, _idleTimeout);
83+
}
84+
}
85+
private bool ShouldRefreshKey(TimeSpan? ttl)
86+
{
87+
return ttl.HasValue && ttl.Value < _refreshThreshold;
88+
}
89+
public async Task RefreshAsync(string key, CancellationToken token = default)
90+
{
91+
string redisKey = FormatKey(key);
92+
await RefreshKeyIfNeededAsync(redisKey);
93+
}
94+
private async Task RefreshKeyIfNeededAsync(string redisKey)
95+
{
96+
var ttl = await _db.KeyTimeToLiveAsync(redisKey);
97+
98+
if (ShouldRefreshKey(ttl))
99+
{
100+
_ = _db.KeyExpireAsync(redisKey, _idleTimeout);
101+
}
102+
}
103+
public void Remove(string key) => _db.KeyDelete(FormatKey(key));
104+
105+
public Task RemoveAsync(string key, CancellationToken token = default)
106+
=> _db.KeyDeleteAsync(FormatKey(key));
107+
108+
public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
109+
{
110+
_db.StringSet(FormatKey(key), value, _idleTimeout);
111+
}
112+
113+
public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default)
114+
{
115+
return _db.StringSetAsync(FormatKey(key), value, _idleTimeout);
116+
}
117+
}
51118

52119
public class TenantMiddleware
53120
{

dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,11 @@ private void ConfigureSessionService(IServiceCollection services, ISessionServic
475475
}
476476
else
477477
{
478-
services.AddStackExchangeRedisCache(options =>
479-
{
480-
GXLogging.Info(log, $"Using Redis for Distributed session, ConnectionString:{sessionService.ConnectionString}, InstanceName: {sessionService.InstanceName}");
481-
options.Configuration = sessionService.ConnectionString;
482-
options.InstanceName = sessionService.InstanceName;
483-
});
478+
GXLogging.Info(log, $"Using Redis for Distributed session, ConnectionString:{sessionService.ConnectionString}, InstanceName: {sessionService.InstanceName}");
479+
480+
services.AddSingleton<IDistributedCache>(sp =>
481+
new CustomRedisSessionStore(sessionService.ConnectionString, TimeSpan.FromMinutes(Preferences.SessionTimeout), sessionService.InstanceName));
482+
484483
services.AddDataProtection().PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(sessionService.ConnectionString), DATA_PROTECTION_KEYS).SetApplicationName(sessionService.InstanceName);
485484
}
486485
}

0 commit comments

Comments
 (0)