fix(templateMatcher): Исправление ошибок в именах шаблонов и рефакторинг синхронизации
- Устранена ошибка, когда при переиспользовании шаблона для шорткодов передавался ЭК "КОМПЛЕКСЫ-[ЗО]" вместо целевого ЭК шаблона. - Проведен небольшой рефакторинг общих процессов синхронизации различных типов групп работ.
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.Job;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||
@@ -10,71 +14,105 @@ namespace PARR.TemplateMatcher.Services.Implementations;
|
||||
internal class TemplateReuser : ITemplateReuser
|
||||
{
|
||||
private readonly ILogger<TemplateReuser> logger;
|
||||
private readonly ITemplateRepository templateService;
|
||||
private readonly ITemplateRepository templateRepository;
|
||||
private readonly ITemplateNameNormalizer nameNormalizer;
|
||||
private readonly ITemplateMqPublisher mqPublisher;
|
||||
|
||||
public TemplateReuser(
|
||||
ILogger<TemplateReuser> logger,
|
||||
ITemplateRepository templateService)
|
||||
ITemplateRepository templateRepository,
|
||||
ITemplateNameNormalizer nameNormalizer,
|
||||
ITemplateMqPublisher mqPublisher)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.templateService = templateService;
|
||||
this.templateRepository = templateRepository;
|
||||
this.nameNormalizer = nameNormalizer;
|
||||
this.mqPublisher = mqPublisher;
|
||||
}
|
||||
|
||||
|
||||
public async Task<Template?> TryReuseOneUnusedTemplateAsync(
|
||||
Guid jobId,
|
||||
Guid unitId,
|
||||
public async Task<bool> TryReuseAsync(
|
||||
Job targetJob,
|
||||
Guid targetUnitId,
|
||||
Unit? targetUnit,
|
||||
int? index,
|
||||
List<UnitInTemplateMessage> unitsInTemplate,
|
||||
bool isActiveTemplate,
|
||||
bool isActiveSchedule,
|
||||
HistoryInitiator initiator,
|
||||
int maxAttempts = 3)
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
const int maxAttempts = 3;
|
||||
|
||||
for (int attempt = 1; attempt <= maxAttempts; attempt++)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
// Атомарно резервируем один шаблон через DAL
|
||||
var templateId = await templateService.ReserveUnusedTemplateAsync(unitId, initiator);
|
||||
|
||||
// 1. Атомарный захват шаблона
|
||||
var templateId = await templateRepository.ReserveUnusedTemplateAsync(targetUnitId, initiator);
|
||||
if (templateId == null)
|
||||
{
|
||||
logger.LogDebug("Нет доступных Unused-шаблонов для переиспользования (попытка {Attempt}).", attempt);
|
||||
return null;
|
||||
logger.LogDebug("Нет доступных Unused-шаблонов (попытка {Attempt}).", attempt);
|
||||
return false; // Шаблоны закончились
|
||||
}
|
||||
|
||||
// Загружаем зарезервированный шаблон
|
||||
var template = await templateService.Get()
|
||||
// Загружаем захваченный шаблон
|
||||
var template = await templateRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Include(t => t.Unit)
|
||||
.Include(t => t.Job)
|
||||
.ThenInclude(t => t!.Tnk)
|
||||
.Include(t => t.Job)
|
||||
.ThenInclude(t => t!.Group)
|
||||
.ThenInclude(t => t!.GroupType)
|
||||
.FirstOrDefaultAsync(t => t.Id == templateId);
|
||||
.FirstOrDefaultAsync(t => t.Id == templateId, ct);
|
||||
|
||||
if (template == null)
|
||||
{
|
||||
logger.LogWarning("Зарезервированный шаблон {TemplateId} не найден при загрузке.", templateId);
|
||||
continue;
|
||||
logger.LogWarning("Зарезервированный шаблон {TemplateId} не найден.", templateId);
|
||||
continue; // Попробовать еще раз
|
||||
}
|
||||
|
||||
logger.LogInformation(
|
||||
"Успешно захвачен шаблон {TemplateId} (старый Job {OldJobId}) для нового Job {NewJobId}, Unit {UnitId} (попытка {Attempt}).",
|
||||
template.Id, template.JobId, jobId, unitId, attempt);
|
||||
logger.LogInformation("Шаблон {TemplateId} захвачен для переиспользования.", templateId);
|
||||
|
||||
return template;
|
||||
// 2. Нормализация имени
|
||||
var templateForName = new Template
|
||||
{
|
||||
Id = template.Id,
|
||||
Name = template.Name,
|
||||
JobId = targetJob.Id,
|
||||
UnitId = targetUnitId,
|
||||
Index = index,
|
||||
Job = targetJob,
|
||||
Unit = targetUnit,
|
||||
UnitsInTemplate = unitsInTemplate.Select(m => new UnitsInTemplate { UnitId = m.UnitId, UnitFieldValueId = m.UnitFieldValueId }).ToList()
|
||||
};
|
||||
|
||||
var expectedName = await nameNormalizer.GetNormalizedTemplateNameAsync(templateForName);
|
||||
|
||||
// 3. Отправка команды в MQ
|
||||
var message = new TemplateUpdaterMessage
|
||||
{
|
||||
TemplateId = template.Id,
|
||||
JobId = targetJob.Id,
|
||||
UnitId = targetUnitId,
|
||||
Name = expectedName,
|
||||
IsActiveTemplate = isActiveTemplate,
|
||||
IsActiveSchedule = isActiveSchedule,
|
||||
StatusTypeId = TemplateStatusTypeEnum.Used,
|
||||
Initiator = initiator,
|
||||
IsNew = true,
|
||||
Index = index ?? template.Index,
|
||||
UnitsInTemplate = unitsInTemplate
|
||||
};
|
||||
|
||||
await mqPublisher.PublishUpdateAsync(message, ct);
|
||||
return true; // Успех
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Ошибка при попытке захвата шаблона (попытка {Attempt}).", attempt);
|
||||
|
||||
if (attempt == maxAttempts)
|
||||
throw;
|
||||
|
||||
// Небольшая задержка перед повтором
|
||||
await Task.Delay(Random.Shared.Next(10, 50));
|
||||
logger.LogError(ex, "Ошибка при переиспользовании (попытка {Attempt}).", attempt);
|
||||
if (attempt == maxAttempts) return false; // После 3 попыток сдаемся
|
||||
await Task.Delay(Random.Shared.Next(10, 50), ct);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user