feat(templateMatcher): Рефакторинг, основной метод синхронизации GroupedTemplateSynchronizer разбит на отдельные классы; Неиспользуемые шаблоны теперь привязываются к ЭК КОСМПЛЕКСЫ-[ЗО].

This commit is contained in:
Mikhail Kuznetsov
2026-05-14 16:47:27 +10:00
parent f7a74d315a
commit 90e6352117
30 changed files with 1150 additions and 864 deletions

View File

@@ -0,0 +1,80 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces;
using PARR.Domain.Entities;
using PARR.Domain.Entities.Base.History;
using PARR.TemplateMatcher.Services.Interfaces;
namespace PARR.TemplateMatcher.Services.Implementations;
internal class TemplateReuser : ITemplateReuser
{
private readonly ILogger<TemplateReuser> logger;
private readonly ITemplateRepository templateService;
public TemplateReuser(
ILogger<TemplateReuser> logger,
ITemplateRepository templateService)
{
this.logger = logger;
this.templateService = templateService;
}
public async Task<Template?> TryReuseOneUnusedTemplateAsync(
Guid jobId,
Guid unitId,
HistoryInitiator initiator,
int maxAttempts = 3)
{
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
// Атомарно резервируем один шаблон через DAL
var templateId = await templateService.ReserveUnusedTemplateAsync(unitId, initiator);
if (templateId == null)
{
logger.LogDebug("Нет доступных Unused-шаблонов для переиспользования (попытка {Attempt}).", attempt);
return null;
}
// Загружаем зарезервированный шаблон
var template = await templateService.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);
if (template == null)
{
logger.LogWarning("Зарезервированный шаблон {TemplateId} не найден при загрузке.", templateId);
continue;
}
logger.LogInformation(
"Успешно захвачен шаблон {TemplateId} (старый Job {OldJobId}) для нового Job {NewJobId}, Unit {UnitId} (попытка {Attempt}).",
template.Id, template.JobId, jobId, unitId, attempt);
return template;
}
catch (Exception ex)
{
logger.LogError(ex, "Ошибка при попытке захвата шаблона (попытка {Attempt}).", attempt);
if (attempt == maxAttempts)
throw;
// Небольшая задержка перед повтором
await Task.Delay(Random.Shared.Next(10, 50));
}
}
return null;
}
}