private (bool success, ServicePriceResponse response) ServicePriceInternal( Guid guid, string concentratorId, string controllerId, int cardType, string cardId, string serviceId, int transactionId, int endpointRssi, int concentratorRssi) { Concentrator getConcentrator() { var repo = _serviceProvider.GetService <ICardSystemRepository <Concentrator> >(); return(repo.AsNoTracking().FirstOrDefault(x => x.DeviceId == concentratorId)); }; ControllerConfigRelay getController() { var repo = _serviceProvider.GetService <ICardSystemRepository <ControllerConfigRelay> >(); return(repo.AsNoTracking() .Include(x => x.EGM) .ThenInclude(x => x.AllowedCurrencies) .FirstOrDefault(x => x.SerialNumber == controllerId && x.OwnerId == _ownerId)); }; Card getCard() { Card entity = null; ICardSystemRepository <Card> repo = null; string cardDBId = CardCacheServiceV2.Instance.GetIdByExternalId(cardId); if (!string.IsNullOrWhiteSpace(cardDBId)) { entity = CardCacheServiceV2.Instance.GetCard(_serviceProvider, cardDBId); if (entity != null) { return(entity); } repo = _serviceProvider.GetService <ICardSystemRepository <Card> >(); entity = repo.AsNoTracking() .Include(x => x.CardMode) .Include(x => x.User) .FirstOrDefault(x => x.Id == cardDBId); if (entity != null) { CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity); CardCacheServiceV2.Instance.AddNewMap(entity); } return(entity); } repo = _serviceProvider.GetService <ICardSystemRepository <Card> >(); entity = repo.AsNoTracking() .Include(x => x.CardMode) .Include(x => x.User) .FirstOrDefault(x => x.ExternalId == cardId); if (entity != null) { CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity); CardCacheServiceV2.Instance.AddNewMap(entity); } return(entity); }; EGM getEGM() { var repo = _serviceProvider.GetService <ICardSystemRepository <EGM> >(); return(repo.AsNoTracking() .Include(x => x.AllowedCurrencies) .Include(x => x.ConfigRelays) .Include(x => x.GameCategory) .Include(x => x.GameManageControllers) .Include(x => x.Images) .Include(x => x.LightingEvent) .Include(x => x.LightingSignals) .Include(x => x.ScheduleDays) .FirstOrDefault(x => x.Id == serviceId)); } var concentrator = getConcentrator(); if (concentrator == null) { var response = new ServicePriceResponse { TransactionId = transactionId, Time = DateTime.UtcNow, ResponseCode = 101, ConcentratorId = concentratorId, ControllerId = controllerId, CardType = cardType, CardId = cardId, CardNumber = string.Empty, ServiceId = string.Empty, ServiceName = string.Empty, Price = 0 }; _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress()); return(false, response); } var controller = getController(); if (controller == null) { var response = new ServicePriceResponse { TransactionId = transactionId, Time = DateTime.UtcNow, ResponseCode = 102, ConcentratorId = concentratorId, ControllerId = controllerId, CardType = cardType, CardId = cardId, CardNumber = string.Empty, ServiceId = string.Empty, ServiceName = string.Empty, Price = 0 }; _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress()); return(false, response); } var card = getCard(); if (card == null) { var response = new ServicePriceResponse { TransactionId = transactionId, Time = DateTime.UtcNow, ResponseCode = 103, ConcentratorId = concentratorId, ControllerId = controllerId, CardType = cardType, CardId = cardId, CardNumber = string.Empty, ServiceId = string.Empty, ServiceName = string.Empty, Price = 0 }; _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress()); return(false, response); } var egm = getEGM(); if (egm == null) { var response = new ServicePriceResponse { TransactionId = transactionId, Time = DateTime.UtcNow, ResponseCode = 132, ConcentratorId = concentratorId, ControllerId = controllerId, CardType = cardType, CardId = cardId, CardNumber = string.Empty, ServiceId = string.Empty, ServiceName = string.Empty, Price = 0 }; _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress()); return(false, response); } IEnumerable <ScheduleDay> getScheduleDays() { IEnumerable <ScheduleDay> egmPriceModifiers = null; var repo = _serviceProvider.GetService <ICardSystemRepository <ScheduleDay> >(); if (!string.IsNullOrWhiteSpace(controller.EGM.Id)) { egmPriceModifiers = repo.AsNoTracking() .Include(x => x.Hours) .Where(x => x.EGMId == controller.EGM.Id) .AsEnumerable(); } if (egmPriceModifiers != null && !egmPriceModifiers.Any()) { egmPriceModifiers = repo .AsNoTracking() .Include(x => x.Hours) .Where(x => x.GameCenterId == controller.EGM.GameCenterId) .AsEnumerable(); } return(egmPriceModifiers ?? new List <ScheduleDay>()); } var scheduleDays = getScheduleDays(); decimal price = _serviceProvider.GetService <ICanPlayService>().GetPricePerGame( _serviceProvider, scheduleDays.ToList(), egm); ServicePriceResponse servicePriceResponse = new ServicePriceResponse { TransactionId = transactionId, Time = DateTime.UtcNow, ResponseCode = 0, ConcentratorId = concentrator.DeviceId, ControllerId = controller.SerialNumber, CardType = card.Type, CardId = card.ExternalId, CardNumber = card.Number, ServiceId = egm.Id, ServiceName = egm.MachineName, Price = (double)price }; _logger.InfoLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | DB Result {JsonSerializer.Serialize(servicePriceResponse, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress()); return(true, servicePriceResponse); }
// метода се извиква при всяко запитване на конектнатия клиент public byte[] ProccessRequest(byte[] message) { //извличане на входните данни var splittedMessage = SplitByteArray(message, 0x1F).ToArray(); if (splittedMessage.Count() == 0) { return new byte[] { 0x45, 0x52, 0x52, 0x4F, 0x52 } } ; //ERROR // how many tokens int tokensCount = splittedMessage.GetLength(0); // command string cmd = tokensCount >= 1 ? new string( splittedMessage[0] .Where(b => b != 0x1F && b != 0x1E) // except: 0x1F - unit separator char(31), 0x1E - record separator char(30) .Select(b => (char)b) .ToArray()) : string.Empty; if (cmd.Equals("RG", StringComparison.InvariantCultureIgnoreCase)) { CanPlayRequest request = CanPlayRequest.DeserializeASCII(splittedMessage); _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(request)); Proto.CanPlayRequest proto_request = request.ToProtoCanPlayRequest(); CanPlayResponse response; try { Proto.CanPlayResponse proto_response = _cardService.CanPlayAsync(proto_request).Result; if (proto_response != null) { response = CanPlayResponse.FromProtoCanPlayResponse(proto_response); } else { response = new CanPlayResponse { Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server" }; _logger.LogError("TextMessageService.ProccessRequest => Proto.CanPlayResponse is null"); } } catch (Exception ex) { response = new CanPlayResponse { Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server" }; _logger.LogError($"TextMessageService.ProccessRequest throws: {ex}"); } _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(response)); return(response.SerializeASCII()); } else if (cmd.Equals("RP", StringComparison.InvariantCultureIgnoreCase)) { ServicePriceRequest request = ServicePriceRequest.DeserializeASCII(splittedMessage); _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(request)); Proto.ServicePriceRequest proto_request = request.ToProtoServicePriceRequest(); ServicePriceResponse response; try { Proto.ServicePriceResponse proto_response = _cardService.ServicePriceAsync(proto_request).Result; if (proto_response != null) { response = ServicePriceResponse.FromProtoServicePriceResponse(proto_response); } else { response = new ServicePriceResponse { Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server" }; _logger.LogError("TextMessageService.ProccessRequest => Proto.ServicePriceRequest is null"); } } catch (Exception ex) { response = new ServicePriceResponse { Success = false, MessageLine1 = "Err 109", MessageLine2 = "Internal server" }; _logger.LogError($"TextMessageService.ProccessRequest throws: {ex}"); } _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(response)); return(response.SerializeASCII()); } else if (cmd.Equals("T", StringComparison.InvariantCultureIgnoreCase)) { return(Encoding.ASCII.GetBytes($"{DateTime.Now:dd.MM.yyyy HH:mm}\x1E")); } else { return(Encoding.ASCII.GetBytes($"{DateTime.Now:dd.MM.yyyy HH:mm}\x1E")); } }
public async ValueTask <ServicePriceResponse> ServicePriceAsync(ServicePriceRequest value, CallContext context = default) { Guid guid = Guid.NewGuid(); _logger.InfoLog($"[CardService.ServicePriceAsync][-IN-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ServiceId {value.ServiceId} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi}", GetIpAddress()); // генерира ключ var key = $"{value.ControllerId}-{value.CardId}-{value.TransactionId}-{value.ServiceId}"; // извлича тюпъл от кеша за този ключ var cachedItem = ServicePriceCacheService.Instance.Get(key, true); // ако има ключ в тюпъла if (!string.IsNullOrWhiteSpace(cachedItem.key)) { // ако има резултат за този ключ в тюпъла if (cachedItem.successResponse != null) { _logger.InfoLog($"[CardService.ServicePriceAsync][-OUT-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ServiceId {value.ServiceId} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi} | CACHED Result", GetIpAddress()); // връща резултата от тюпъла return(cachedItem.successResponse); } } // резервира семафора за текущия тред и продължава, други тредове стигнали до тук чакат ... await semaphoreSlim.WaitAsync(); // проверява за евнтуален тюпъл и резултат за този ключ от други тредове cachedItem = ServicePriceCacheService.Instance.Get(key); if (cachedItem.successResponse != null) { _logger.InfoLog($"[CardService.ServicePriceAsync][-OUT-] [{guid}] TransactionId {value.TransactionId} | ConcentratorId {value.ConcentratorId} | ControllerId {value.ControllerId} | CardType {value.CardType} | CardId {value.CardId} | ServiceId {value.ServiceId} | EndpointRssi: {value.EndpointRssi} | ConcentratorRssi {value.ConcentratorRssi} | CACHED Result", GetIpAddress()); // освобождава семафора за следващи тредове, които чакат semaphoreSlim.Release(); // връща резултата от тюпъла return(cachedItem.successResponse); } // резервира ключа в кеша, като създава тюпъл с този ключ, но без резултат ServicePriceCacheService.Instance.Add(key, (key, null)); ServicePriceResponse response = null; try { // извлича резултата от апи-то (отнема много време) var tupleResult = ServicePriceInternal(guid, value.ConcentratorId, value.ControllerId, value.CardType, value.CardId, value.ServiceId, value.TransactionId, value.EndpointRssi, value.ConcentratorRssi); if (tupleResult.success) { // обновява резултата в тюпъла в кеша за резервирания ключ ServicePriceCacheService.Instance.Add(key, (key, tupleResult.response)); } // връща резултата от апи-то response = tupleResult.response; } finally { // освобождава семафора за следващи тредове, които чакат semaphoreSlim.Release(); } return(response ?? new ServicePriceResponse { TransactionId = value.TransactionId, Time = DateTime.UtcNow, ResponseCode = 109, ConcentratorId = value.ConcentratorId, ControllerId = value.ControllerId, CardType = value.CardType, CardId = value.CardId, CardNumber = string.Empty, ServiceId = string.Empty, ServiceName = string.Empty, Price = 0 }); }