118 lines
4.6 KiB
C#
118 lines
4.6 KiB
C#
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.JobEntities;
|
|
using PARR.Domain.Entities.Unit;
|
|
using PARR.Domain.Enums;
|
|
using PARR.TemplateMatcher.Services.Interfaces;
|
|
|
|
namespace PARR.TemplateMatcher.Services.Implementations;
|
|
|
|
internal class TemplateReuser : ITemplateReuser
|
|
{
|
|
private readonly ILogger<TemplateReuser> logger;
|
|
private readonly ITemplateRepository templateRepository;
|
|
private readonly ITemplateNameNormalizer nameNormalizer;
|
|
private readonly ITemplateMqPublisher mqPublisher;
|
|
|
|
public TemplateReuser(
|
|
ILogger<TemplateReuser> logger,
|
|
ITemplateRepository templateRepository,
|
|
ITemplateNameNormalizer nameNormalizer,
|
|
ITemplateMqPublisher mqPublisher)
|
|
{
|
|
this.logger = logger;
|
|
this.templateRepository = templateRepository;
|
|
this.nameNormalizer = nameNormalizer;
|
|
this.mqPublisher = mqPublisher;
|
|
}
|
|
|
|
public async Task<bool> TryReuseAsync(
|
|
Job targetJob,
|
|
Guid targetUnitId,
|
|
Unit? targetUnit,
|
|
int? index,
|
|
List<UnitInTemplateMessage> unitsInTemplate,
|
|
bool isActiveTemplate,
|
|
bool isActiveSchedule,
|
|
HistoryInitiator initiator,
|
|
CancellationToken ct = default)
|
|
{
|
|
const int maxAttempts = 3;
|
|
|
|
for (int attempt = 1; attempt <= maxAttempts; attempt++)
|
|
{
|
|
ct.ThrowIfCancellationRequested();
|
|
|
|
try
|
|
{
|
|
// 1. Атомарный захват шаблона
|
|
var templateId = await templateRepository.ReserveUnusedTemplateAsync(targetUnitId, initiator);
|
|
if (templateId == null)
|
|
{
|
|
logger.LogDebug("Нет доступных Unused-шаблонов (попытка {Attempt}).", attempt);
|
|
return false; // Шаблоны закончились
|
|
}
|
|
|
|
// Загружаем захваченный шаблон
|
|
var template = await templateRepository.Get()
|
|
.AsNoTracking()
|
|
.Include(t => t.Unit)
|
|
.FirstOrDefaultAsync(t => t.Id == templateId, ct);
|
|
|
|
if (template == null)
|
|
{
|
|
logger.LogWarning("Зарезервированный шаблон {TemplateId} не найден.", templateId);
|
|
continue; // Попробовать еще раз
|
|
}
|
|
|
|
logger.LogInformation("Шаблон {TemplateId} захвачен для переиспользования.", templateId);
|
|
|
|
// 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) return false; // После 3 попыток сдаемся
|
|
await Task.Delay(Random.Shared.Next(10, 50), ct);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
} |