using EVCB_OCPP.DBAPI.Services.DbService; using EVCB_OCPP.Domain.Models.MainDb; using Newtonsoft.Json; using NRedisStack.RedisStackCommands; using Quartz.Impl.AdoJobStore.Common; using StackExchange.Redis; using System.Collections.Generic; using static System.Runtime.InteropServices.JavaScript.JSType; namespace EVCB_OCPP.DBAPI.Services.ServerMessageServices; public class RedisServerMessageService : IServerMessageService { private const string ServerMessageCntKey = "ServerMessageCntKey"; private const string ServerMessageObjectPrefix = "ServerMessageObjectPrefix_"; private string ServerMessageObjectPattern => "ServerMessageObjectPrefix_*"; private readonly IMainDbService mainDbService; private readonly IDatabase redisDatabase; private readonly IServer redisServer; public RedisServerMessageService( IMainDbService mainDbService, IDatabase redisDatabase, IServer redisServer) { this.mainDbService = mainDbService; this.redisDatabase = redisDatabase; this.redisServer = redisServer; } public async ValueTask AddServerMessage(string ChargeBoxId, string OutAction, string OutRequest, string CreatedBy, DateTime? CreatedOn = null, string SerialNo = "", string InMessage = "", CancellationToken token = default) { if (string.IsNullOrEmpty(SerialNo)) { SerialNo = Guid.NewGuid().ToString(); } var _CreatedOn = CreatedOn ?? DateTime.UtcNow; string _OutRequest = OutRequest is not null ? OutRequest : ""; var data = new ServerMessage() { ChargeBoxId = ChargeBoxId, CreatedBy = CreatedBy, CreatedOn = _CreatedOn, OutAction = OutAction, OutRequest = _OutRequest, SerialNo = SerialNo, InMessage = InMessage }; await StoreIntoRedis(data); return SerialNo; } public async ValueTask> GetNeedSendToClientServerMessages() { var allServerMessage = await GetServerMessages(); DateTime startDt = DateTime.UtcNow.AddSeconds(-30); var seperatedServerMessage = allServerMessage.GroupBy(x => x.CreatedOn < startDt).ToDictionary(x => x.Key, x => x?.ToList()); var deprecatedServerMessages = seperatedServerMessage.GetValueOrDefault(true, null); if (deprecatedServerMessages is not null) { var deprecatedServerMessageIds = deprecatedServerMessages.Select(x => x.Id); await RemoveFromRedis(deprecatedServerMessages); foreach (var servermessage in deprecatedServerMessages) { _ = AddServerMessageToDbAsync(servermessage); } } var toReturn = seperatedServerMessage.GetValueOrDefault(false, new List())!; if (allServerMessage.Count > 0) { } if (toReturn.Count > 0) { } return toReturn; } public async ValueTask> GetServerMessages() { //var msgs = await redisDatabase.SortedSetRangeByScoreAsync(ServerMessageSetsKey); var keys = redisServer.Keys(pattern: ServerMessageObjectPattern); var msgs = redisDatabase.StringGet(keys.ToArray()); List toReturn = new List(); foreach (var msg in msgs) { try { var result = JsonConvert.DeserializeObject(msg); toReturn.Add(result); } catch(Exception e) { } } return toReturn; } public ValueTask SaveCompletedMessageToDb() { return ValueTask.CompletedTask; } public async ValueTask SetServerMessageResponseReceived(int id, string InMessage = "", DateTime ReceivedOn = default) { DateTime _ReceivedOn = ReceivedOn == default ? DateTime.UtcNow : ReceivedOn; var key = GetKeyById(id); var redisValue = redisDatabase.StringGet(key); redisDatabase.KeyDelete(key); //var redisServerMessages = provider.RedisCollection(); //var msgs = await redisDatabase.SortedSetRangeByScoreAsync(ServerMessageSetsKey, id, id); //var removedCnt = await redisDatabase.SortedSetRemoveAsync(ServerMessageSetsKey, msgs); var msg = JsonConvert.DeserializeObject(redisValue); msg.Id = 0; msg.InMessage = InMessage; msg.ReceivedOn = _ReceivedOn; var addServerMessageResult = await mainDbService.AddServerMessage(msg); return !string.IsNullOrEmpty(addServerMessageResult); } public async ValueTask SetServerMessageServerHandling(int id, DateTime UpdatedOn = default) { DateTime _UpdatedOn = UpdatedOn == default ? DateTime.UtcNow : UpdatedOn; var key = GetKeyById(id); //var msgs = await redisDatabase.SortedSetRangeByScoreAsync(ServerMessageSetsKey, id, id); //var removedCnt = await redisDatabase.SortedSetRemoveAsync(ServerMessageSetsKey, msgs); //var redisMsg = msgs.FirstOrDefault(); var redisMsg = redisDatabase.StringGet(key); var msg = JsonConvert.DeserializeObject(redisMsg); msg.UpdatedOn = _UpdatedOn; redisDatabase.StringSet(key, JsonConvert.SerializeObject(msg)); //await redisDatabase.SortedSetAddAsync(ServerMessageSetsKey, JsonConvert.SerializeObject(msg), id); return true; } private async ValueTask StoreIntoRedis(ServerMessage data) { data.Id = await GetNextIndex(); var key = GetKeyById(data.Id); redisDatabase.StringSet(key, JsonConvert.SerializeObject(data)); //var result = await redisDatabase.SortedSetAddAsync(ServerMessageSetsKey, JsonConvert.SerializeObject(data), data.Id); return; } private async Task GetNextIndex() { var index = await redisDatabase.StringIncrementAsync(ServerMessageCntKey); return (int)index; } private async Task RemoveFromRedis(IEnumerable datas) { //RedisValue[] ids = Array.ConvertAll(datas.Select(x => x.Id).ToArray() , x => (RedisValue)x); var ids = datas.Select(x => GetKeyById(x.Id)); foreach (var id in ids) { //var deletedCnts = await redisDatabase.SortedSetRemoveRangeByScoreAsync(ServerMessageSetsKey, id, id); //redisDatabase.StringGetDelete(id); redisDatabase.KeyDelete(id); } return; } private async ValueTask AddServerMessageToDbAsync(ServerMessage message) { var memMessageId = message.Id; var addServerMessageResult = await mainDbService.AddServerMessage(message); if (!string.IsNullOrEmpty(addServerMessageResult)) { return memMessageId; } return -1; } private string GetKeyById(int id) { return ServerMessageObjectPattern.Replace("*", id.ToString()); } }