Inizio sistemazione cache redis x utenti

This commit is contained in:
Samuele Locatelli
2023-05-26 18:01:35 +02:00
parent 335557eb7c
commit aff6a89b73
4 changed files with 203 additions and 13 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>0.9.2305.2617</version>
<url>http://nexus.steamware.net/repository/SWS/WDC/stable/WDC.UI.zip</url>
<url>http://nexus.steamware.net/repository/SWS/WDC/stable/WDC.API.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/WDC/stable/ChangeLog.html</changelog>
<mandatory>false</mandatory>
</item>
+1
View File
@@ -49,6 +49,7 @@ namespace WebDoorCreator.Core
public const string rKeyOrderStatus = $"{redisBaseAddr}:Cache:OrderStatus";
public const string rKeyRoles = $"{redisBaseAddr}:Cache:Roles";
public const string rKeyUsers = $"{redisBaseAddr}:Cache:Users";
public const string rKeyUsersAll = $"{redisBaseAddr}:Cache:UsersAll";
public const string rKeyUsersView = $"{redisBaseAddr}:Cache:UsersView";
public const string rKeyVocLemma = $"{redisBaseAddr}:Cache:VocLemma";
public const string rKeyLanguage = $"{redisBaseAddr}:Cache:Languages";
@@ -2280,12 +2280,6 @@ namespace WebDoorCreator.Data.Services
#endregion Public Methods
#region Protected Fields
protected Random rnd = new Random();
#endregion Protected Fields
#region Protected Properties
protected WebDoorCreator.Data.DDF.Converter currDdfConv { get; set; } = null!;
@@ -2295,11 +2289,8 @@ namespace WebDoorCreator.Data.Services
#region Private Fields
private static IConfiguration _configuration = null!;
private static JsonSerializerSettings? JSSettings;
private static Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
/// <summary>
@@ -2322,6 +2313,8 @@ namespace WebDoorCreator.Data.Services
/// </summary>
private IDatabase redisDb = null!;
private Random rnd = new Random();
#endregion Private Fields
#region Private Properties
+199 -3
View File
@@ -1,4 +1,14 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using NLog;
using NLog.Fluent;
using Org.BouncyCastle.Asn1.X500;
using StackExchange.Redis;
using System.Diagnostics;
using WebDoorCreator.Core;
using WebDoorCreator.Data.DbModels;
using WebDoorCreator.Data.User;
namespace WebDoorCreator.UI.Data
@@ -7,9 +17,102 @@ namespace WebDoorCreator.UI.Data
{
#region Public Constructors
public WDCUserService(UserManager<IdentityUser> userManager)
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Durata cache lunga IN SECONDI
/// </summary>
private int cacheTtlLong = 60 * 5;
/// <summary>
/// Durata cache breve IN SECONDI
/// </summary>
private int cacheTtlShort = 60 * 1;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private IConnectionMultiplexer redisConn;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private static JsonSerializerSettings? JSSettings;
/// <summary>
/// Durata cache breve (1 min circa + perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan FastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan LongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata cache molto breve (10 sec circa + perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan UltraFastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort / 6 * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan UltraLongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
}
private Random rnd = new Random();
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
{
bool answ = false;
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
var server = redisConn.GetServer(endPoint);
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
answ = true;
}
}
return answ;
}
public WDCUserService(IConnectionMultiplexer redisConnMult, UserManager<IdentityUser> userManager)
{
_userManager = userManager;
// Conf cache
redisConn = redisConnMult;
redisDb = this.redisConn.GetDatabase();
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
JSSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
// chiudo log
Log.Info("Avviata classe WDCUserService");
}
#endregion Public Constructors
@@ -102,7 +205,51 @@ namespace WebDoorCreator.UI.Data
#region Public Methods
/// <summary>
/// Dati utente (filtrati da searchVal)
/// Dati utente (TUTTI) da REDIS o DB
/// </summary>
/// <returns></returns>
public async Task<List<IdentityUser>> UserDataGetAll()
{
string source = "DB";
List<IdentityUser> dbResult = new List<IdentityUser>();
// cerco da cache
string currKey = $"{Constants.rKeyUsersAll}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<IdentityUser>>(rawData);
if (tempResult == null)
{
dbResult = new List<IdentityUser>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = await _userManager.Users.ToListAsync();
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dbResult == null)
{
dbResult = new List<IdentityUser>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"UserDataGetAll | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
/// <summary>
/// Dati utente (filtrati da UserId)
/// </summary>
/// <param name="searchVal"></param>
/// <returns></returns>
@@ -111,8 +258,11 @@ namespace WebDoorCreator.UI.Data
// Collezione utenti
List<IdentityUser> RawList = new List<IdentityUser>();
List<UserData> UsersList = new List<UserData>();
#if false
// recupero utenti da obj _userManager
var allData = _userManager.Users.ToList();
var allData = _userManager.Users.ToList();
#endif
var allData = await UserDataGetAll();
if (!string.IsNullOrEmpty(searchVal))
{
RawList = allData.Where(x => x.NormalizedEmail.Contains(searchVal.ToUpper()) || x.NormalizedUserName.Contains(searchVal.ToUpper())).ToList();
@@ -147,6 +297,52 @@ namespace WebDoorCreator.UI.Data
return await Task.FromResult(UsersList);
}
/// <summary>
/// Dati utente (singolo x UserId)
/// </summary>
/// <param name="UserId"></param>
/// <returns></returns>
public async Task<List<UserData>> UserDataGetById(string UserId)
{
// Collezione utenti
List<IdentityUser> RawList = new List<IdentityUser>();
List<UserData> UsersList = new List<UserData>();
// recupero utenti da obj _userManager
var allData = _userManager.Users.ToList();
if (!string.IsNullOrEmpty(UserId))
{
RawList = allData.Where(x => x.NormalizedEmail.Contains(UserId.ToUpper()) || x.NormalizedUserName.Contains(UserId.ToUpper())).ToList();
}
else
{
RawList = allData;
}
var user = RawList.Select(x => new IdentityUser
{
Id = x.Id,
UserName = x.UserName,
Email = x.Email,
PhoneNumber = x.PhoneNumber,
PasswordHash = "*****",
EmailConfirmed = x.EmailConfirmed
}).ToList();
foreach (var item in user)
{
var UserRoles = await _userManager.GetRolesAsync(item);
var UserClaims = await _userManager.GetClaimsAsync(item);
var newItem = new UserData()
{
Identity = item,
Roles = UserRoles.ToList(),
Claims = UserClaims.ToList()
};
UsersList.Add(newItem);
}
return await Task.FromResult(UsersList);
}
#endregion Public Methods
#region Protected Methods