158 lines
5.4 KiB
C#
158 lines
5.4 KiB
C#
using MP.Core.DTO;
|
|
using StackExchange.Redis;
|
|
|
|
namespace MP.RIOC.Services
|
|
{
|
|
public class RedisWeightProvider : IWeightProvider
|
|
{
|
|
#region Public Constructors
|
|
|
|
public RedisWeightProvider(IConnectionMultiplexer mux, IConfiguration config)
|
|
{
|
|
_config = config;
|
|
_db = mux.GetDatabase();
|
|
_mux = mux;
|
|
_defaultOld = config.GetValue<int>("RouteMan:DefaultWeightOld", 100);
|
|
_defaultNew = config.GetValue<int>("RouteMan:DefaultWeightNew", 0);
|
|
_redisBaseKey = config.GetValue<string>("ServerConf:RedisBaseKey") ?? "MP_IOC";
|
|
_keyPrefix = $"{_redisBaseKey}:route_weight:";
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Ritorna (oldWeight, newWeight) per il metodo. Se non esiste, crea la chiave con i default.
|
|
/// </summary>
|
|
public (int oldWeight, int newWeight) GetWeightsFor(string method)
|
|
{
|
|
if (string.IsNullOrEmpty(method)) method = "unknown";
|
|
var key = _keyPrefix + method;
|
|
|
|
// Leggi entrambi i campi
|
|
var oldVal = _db.HashGet(key, "old");
|
|
var newVal = _db.HashGet(key, "new");
|
|
|
|
// Se entrambi mancanti, inizializza con default (usando HSet con When.NotExists per evitare overwrite)
|
|
if (oldVal.IsNull && newVal.IsNull)
|
|
{
|
|
// Imposta i campi singolarmente con When.NotExists per evitare overwrite
|
|
_db.HashSet(key, "old", _defaultOld, When.NotExists);
|
|
_db.HashSet(key, "new", _defaultNew, When.NotExists);
|
|
|
|
// Rileggi per essere sicuri
|
|
oldVal = _db.HashGet(key, "old");
|
|
newVal = _db.HashGet(key, "new");
|
|
}
|
|
|
|
// Se uno dei due manca, impostalo al default (non sovrascrive l'altro)
|
|
if (oldVal.IsNull)
|
|
{
|
|
_db.HashSet(key, "old", _defaultOld, When.NotExists);
|
|
oldVal = _defaultOld;
|
|
}
|
|
if (newVal.IsNull)
|
|
{
|
|
_db.HashSet(key, "new", _defaultNew, When.NotExists);
|
|
newVal = _defaultNew;
|
|
}
|
|
|
|
if (!int.TryParse(oldVal.ToString(), out var oldW)) oldW = _defaultOld;
|
|
if (!int.TryParse(newVal.ToString(), out var newW)) newW = _defaultNew;
|
|
|
|
// clamp 0..100
|
|
oldW = Math.Clamp(oldW, 0, 100);
|
|
newW = Math.Clamp(newW, 0, 100);
|
|
|
|
return (oldW, newW);
|
|
}
|
|
|
|
// API per aggiornare i pesi a runtime (opzionale)
|
|
public void SetWeights(string method, int oldWeight, int newWeight)
|
|
{
|
|
var key = _keyPrefix + (string.IsNullOrEmpty(method) ? "unknown" : method);
|
|
_db.HashSet(key, new HashEntry[] {
|
|
new HashEntry("old", Math.Clamp(oldWeight,0,100)),
|
|
new HashEntry("new", Math.Clamp(newWeight,0,100))
|
|
});
|
|
}
|
|
|
|
public async Task<List<WeightDTO>> GetAllWeightsAsync()
|
|
{
|
|
var result = new List<WeightDTO>();
|
|
var server = _mux.GetServer(_mux.GetEndPoints().First());
|
|
|
|
if (server.IsReplica)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
await foreach (var key in server.KeysAsync(pattern: $"{_keyPrefix}*"))
|
|
{
|
|
var methodName = KeyToString(key.ToString());
|
|
if (string.IsNullOrEmpty(methodName)) continue;
|
|
|
|
var oldVal = _db.HashGet(key, "old");
|
|
var newVal = _db.HashGet(key, "new");
|
|
|
|
int oldW = 100;
|
|
int newW = 0;
|
|
|
|
if (!oldVal.IsNull && int.TryParse(oldVal.ToString(), out var parsedOld))
|
|
oldW = Math.Clamp(parsedOld, 0, 100);
|
|
|
|
if (!newVal.IsNull && int.TryParse(newVal.ToString(), out var parsedNew))
|
|
newW = Math.Clamp(parsedNew, 0, 100);
|
|
|
|
result.Add(new WeightDTO { Method = methodName, OldWeight = oldW, NewWeight = newW });
|
|
}
|
|
|
|
// riordino desc x NEW poi alfabetico...
|
|
result = result
|
|
.OrderByDescending(x => x.NewWeight)
|
|
.ThenBy(x => x.Method)
|
|
.ToList();
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool UpsertWeight(WeightDTO updRecord)
|
|
{
|
|
if (updRecord == null || string.IsNullOrEmpty(updRecord.Method))
|
|
return false;
|
|
|
|
var key = _keyPrefix + updRecord.Method;
|
|
_db.HashSet(key, new HashEntry[] {
|
|
new HashEntry("old", Math.Clamp(updRecord.OldWeight, 0, 100)),
|
|
new HashEntry("new", Math.Clamp(updRecord.NewWeight, 0, 100))
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
private string KeyToString(string key)
|
|
{
|
|
if (string.IsNullOrEmpty(key)) return "";
|
|
var prefix = _keyPrefix ?? "";
|
|
if (key.StartsWith(prefix))
|
|
return key.Substring(prefix.Length);
|
|
return key;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Fields
|
|
|
|
private static string _keyPrefix = "route_weight:";
|
|
private static string _redisBaseKey = "";
|
|
private readonly IConfiguration _config;
|
|
private readonly IDatabase _db;
|
|
private readonly IConnectionMultiplexer _mux;
|
|
private readonly int _defaultNew;
|
|
private readonly int _defaultOld;
|
|
|
|
#endregion Private Fields
|
|
}
|
|
}
|