diff --git a/PARR.DAL/DomainServices/Shortcodes/ShortcodesService.cs b/PARR.DAL/DomainServices/Shortcodes/ShortcodesService.cs index cc9b2dc9..1c3b6150 100644 --- a/PARR.DAL/DomainServices/Shortcodes/ShortcodesService.cs +++ b/PARR.DAL/DomainServices/Shortcodes/ShortcodesService.cs @@ -738,7 +738,8 @@ namespace PARR.DAL.DomainServices.Shortcodes return NoContent; } - var cacheKey = $"gr_shcd_{jobGroupId:N}_{unitId:N}_{ComputeHash(fullShortcode)}"; + //var cacheKey = $"gr_shcd_{jobGroupId:N}_{unitId:N}_{ComputeHash(fullShortcode)}"; + var cacheKey = cacheService.GetKey(new[] { "grouped", "shortcode", $"{jobGroupId:N}", $"{unitId:N}" }, new[] { fullShortcode }); var cachedData = await cacheService.GetCachedDataAsync(cacheKey).ConfigureAwait(false); if (cachedData != null) @@ -872,12 +873,5 @@ namespace PARR.DAL.DomainServices.Shortcodes } return result.ToString(); } - - private static string ComputeHash(string input) - { - using var sha256 = System.Security.Cryptography.SHA256.Create(); - var hashedBytes = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)); - return Convert.ToBase64String(hashedBytes).Replace('+', '-').Replace('/', '_').Substring(0, 16); - } } } \ No newline at end of file diff --git a/PARR.DAL/DomainServices/UnitFilterService/UnitFilterService.cs b/PARR.DAL/DomainServices/UnitFilterService/UnitFilterService.cs index e8299f49..19040d7f 100644 --- a/PARR.DAL/DomainServices/UnitFilterService/UnitFilterService.cs +++ b/PARR.DAL/DomainServices/UnitFilterService/UnitFilterService.cs @@ -566,6 +566,7 @@ internal class UnitFilterService : IUnitFilterService return result; } + /// /// Формируем итоговый результат /// @@ -781,6 +782,7 @@ internal class UnitFilterService : IUnitFilterService return result.ToList(); } + #region вспомогательные методы /// /// Применяет фильтры к связям (родителям или детям) @@ -959,7 +961,6 @@ internal class UnitFilterService : IUnitFilterService } - private async Task> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter, CancellationToken cancellationToken = default) { // var cacheKey = cacheService.GetKey(new[] { "uf_ids", filter.UnitFilter }, isUseHash: true); @@ -991,7 +992,6 @@ internal class UnitFilterService : IUnitFilterService } - /// /// Обрабатывает маску LIKE для корректной работы с SQL /// diff --git a/PARR.DAL/Services/Implementations/TemplateService.cs b/PARR.DAL/Services/Implementations/TemplateService.cs index cc1b2c9b..731e797f 100644 --- a/PARR.DAL/Services/Implementations/TemplateService.cs +++ b/PARR.DAL/Services/Implementations/TemplateService.cs @@ -109,61 +109,64 @@ namespace PARR.DAL.Services.Implementations } - public async Task ReserveUnusedTemplateAsync(Guid newUnitId, HistoryInitiator initiator) + public async Task ReserveUnusedTemplateAsync(Guid newUnitId, Guid newJobId, HistoryInitiator initiator) { - logger.LogDebug("Резервирую неиспользуемый шаблон с проверкой конфигураций роботов для UnitId: {UnitId}", newUnitId); + logger.LogDebug("Резервирую неиспользуемый шаблон с проверкой конфигураций роботов для UnitId: {UnitId}, JobId: {JobId}", newUnitId, newJobId); var sql = @" - UPDATE ""Templates"" - SET ""StatusTypeId"" = @NewStatus, - ""DateModified"" = @DateModified, - ""InitiatorIp"" = @InitiatorIp, - ""InitiatorParrComponentId"" = @InitiatorComponent, - ""InitiatorComment"" = @InitiatorComment - WHERE ""Id"" = ( - SELECT t.""Id"" - FROM ""Templates"" t - WHERE t.""StatusTypeId"" = @OldStatus - AND t.""UnitId"" != @NewUnitId - AND EXISTS ( - SELECT 1 - FROM ""RobotConfigurations"" rc - WHERE rc.""TemplateId"" = t.""Id"" - AND rc.""RobotCode"" = @RobotCode1 - AND rc.""TaskStatusCode"" = @TaskStatus - AND rc.""RobotStatusCode"" = @RobotStatus - ) - AND EXISTS ( - SELECT 1 - FROM ""RobotConfigurations"" rc - WHERE rc.""TemplateId"" = t.""Id"" - AND rc.""RobotCode"" = @RobotCode2 - AND rc.""TaskStatusCode"" = @TaskStatus - AND rc.""RobotStatusCode"" = @RobotStatus - ) - ORDER BY t.""DateCreated"" ASC - LIMIT 1 - ) - RETURNING ""Id"";"; + UPDATE ""Templates"" + SET ""StatusTypeId"" = @NewStatus, + ""DateModified"" = @DateModified, + ""UnitId"" = @NewUnitId, + ""JobId"" = @NewJobId, + ""InitiatorIp"" = @InitiatorIp, + ""InitiatorParrComponentId"" = @InitiatorComponent, + ""InitiatorComment"" = @InitiatorComment + WHERE ""Id"" = ( + SELECT t.""Id"" + FROM ""Templates"" t + WHERE t.""StatusTypeId"" = @OldStatus + AND t.""UnitId"" != @NewUnitId + AND EXISTS ( + SELECT 1 + FROM ""RobotConfigurations"" rc + WHERE rc.""TemplateId"" = t.""Id"" + AND rc.""RobotCode"" = @RobotCode1 + AND rc.""TaskStatusCode"" = @TaskStatus + AND rc.""RobotStatusCode"" = @RobotStatus + ) + AND EXISTS ( + SELECT 1 + FROM ""RobotConfigurations"" rc + WHERE rc.""TemplateId"" = t.""Id"" + AND rc.""RobotCode"" = @RobotCode2 + AND rc.""TaskStatusCode"" = @TaskStatus + AND rc.""RobotStatusCode"" = @RobotStatus + ) + ORDER BY t.""DateCreated"" ASC + LIMIT 1 + ) + RETURNING ""Id"";"; var parameters = new[] { - new NpgsqlParameter("@NewStatus", (int)TemplateStatusTypeEnum.Updating), - new NpgsqlParameter("@DateModified", DateTimeOffset.UtcNow), - new NpgsqlParameter("@InitiatorIp", initiator.InitiatorIp ?? (object)DBNull.Value), - new NpgsqlParameter("@InitiatorComponent", - initiator.InitiatorParrComponentId.HasValue - ? (object)(int)initiator.InitiatorParrComponentId.Value - : DBNull.Value), - new NpgsqlParameter("@InitiatorComment", initiator.InitiatorComment ?? (object)DBNull.Value), - new NpgsqlParameter("@OldStatus", (int)TemplateStatusTypeEnum.Unused), - new NpgsqlParameter("@NewUnitId", newUnitId), - // Параметры для проверки конфигураций роботов - new NpgsqlParameter("@RobotCode1", 1), - new NpgsqlParameter("@RobotCode2", 2), - new NpgsqlParameter("@TaskStatus", 30), - new NpgsqlParameter("@RobotStatus", 44) - }; + new NpgsqlParameter("@NewStatus", (int)TemplateStatusTypeEnum.Updating), + new NpgsqlParameter("@DateModified", DateTimeOffset.UtcNow), + new NpgsqlParameter("@NewUnitId", newUnitId), + new NpgsqlParameter("@NewJobId", newJobId), + new NpgsqlParameter("@InitiatorIp", initiator.InitiatorIp ?? (object)DBNull.Value), + new NpgsqlParameter("@InitiatorComponent", + initiator.InitiatorParrComponentId.HasValue + ? (object)(int)initiator.InitiatorParrComponentId.Value + : DBNull.Value), + new NpgsqlParameter("@InitiatorComment", initiator.InitiatorComment ?? (object)DBNull.Value), + new NpgsqlParameter("@OldStatus", (int)TemplateStatusTypeEnum.Unused), + // Параметры для проверки конфигураций роботов + new NpgsqlParameter("@RobotCode1", (int)RobotsEnum.TemplateOrder), + new NpgsqlParameter("@RobotCode2", (int)RobotsEnum.ScheduleOrder), + new NpgsqlParameter("@TaskStatus", (int)TaskStatusEnum.Ok), + new NpgsqlParameter("@RobotStatus", (int)RobotStatusEnum.Complete) + }; try { @@ -175,19 +178,19 @@ namespace PARR.DAL.Services.Implementations if (reservedTemplateId != default(Guid)) { - logger.LogInformation("Успешно зарезервирован шаблон с ID: {TemplateId} для UnitId: {UnitId}", - reservedTemplateId, newUnitId); + logger.LogInformation("Успешно зарезервирован шаблон с ID: {TemplateId} для UnitId: {UnitId}, JobId: {JobId}", + reservedTemplateId, newUnitId, newJobId); } else { - logger.LogDebug("Не удалось зарезервировать шаблон для UnitId: {UnitId} (не найдено подходящих конфигураций роботов)", newUnitId); + logger.LogDebug("Не удалось зарезервировать шаблон для UnitId: {UnitId}, JobId: {JobId} (не найдено подходящих конфигураций роботов)", newUnitId, newJobId); } return reservedTemplateId; } catch (Exception ex) { - logger.LogError(ex, "Ошибка при резервировании шаблона для UnitId: {UnitId}", newUnitId); + logger.LogError(ex, "Ошибка при резервировании шаблона для UnitId: {UnitId}, JobId: {JobId}", newUnitId, newJobId); throw; } } diff --git a/PARR.DAL/Services/Interfaces/ITemplateService.cs b/PARR.DAL/Services/Interfaces/ITemplateService.cs index 3b5d72b5..31bd1385 100644 --- a/PARR.DAL/Services/Interfaces/ITemplateService.cs +++ b/PARR.DAL/Services/Interfaces/ITemplateService.cs @@ -8,7 +8,18 @@ namespace PARR.DAL.Services.Interfaces { Task GetTemplateByNameAsync(string name); - Task ReserveUnusedTemplateAsync(Guid newUnitId, HistoryInitiator initiator); + /// + /// Резервирует неиспользуемый шаблон для указанного ЭК и работы. + /// Для корректного расчета NextRun назначает захваченному шаблону ЭК и работу + /// + /// Id ЭК. + /// Id работы. + /// Данные инициатора операции. + /// + /// Id зарезервированного шаблона или , + /// если подходящий шаблон не найден. + /// + Task ReserveUnusedTemplateAsync(Guid newUnitId, Guid newJobId, HistoryInitiator initiator); IQueryable