Files
parr_api/PARR.TemplateMatcher/TemplateMatcher.cs

266 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.Common.Domain;
using PARR.Constants;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.Models;
using PARR.DAL.Models.Job;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.TemplateMatcher.Settings;
using System.Text.Json;
namespace PARR.TemplateMatcher
{
internal class TemplateMatcher : ITemplateMatcher
{
private readonly ILogger<TemplateMatcher> logger;
private readonly IUnitFilterService unitFilterService;
private readonly MqSettings mqSettings;
private readonly IMqService mqService;
private readonly ITemplateService templateService;
private readonly IJobService jobService;
private readonly IShortcodesService shortcodesService;
public TemplateMatcher(
ILogger<TemplateMatcher> logger,
IUnitFilterService unitFilterService,
MqSettings mqSettings,
IMqService mqService,
ITemplateService templateService,
IJobService jobService,
IShortcodesService shortcodesService
)
{
this.logger = logger;
this.unitFilterService = unitFilterService;
this.mqSettings = mqSettings;
this.mqService = mqService;
this.templateService = templateService;
this.jobService = jobService;
this.shortcodesService = shortcodesService;
}
public async Task SyncTemplatesForJob(Guid jobId, HistoryInitiator initiator)
{
logger.LogDebug("Начало синхронизации шаблонов для JobId {JobId}", jobId);
// 1. Получаем UnitId, которые должны иметь шаблоны (по фильтрам Job)
var units = await unitFilterService.GetUnitsIdByJobFilterAsync(jobId);
if (units == null)
{
logger.LogWarning("Для JobId {JobId} фильтр вернул null. Пропускаем.", jobId);
return;
}
var expectedUnitIds = units.ToHashSet();
logger.LogDebug("Для JobId {JobId} найдено {Count} Unit'ов, соответствующих фильтрам.", jobId, expectedUnitIds.Count);
if (!expectedUnitIds.Any())
{
logger.LogInformation("Для JobId {JobId} не найдено Unit'ов, соответствующих фильтрам.", jobId);
return;
}
// 2. Получаем все шаблоны для этого Job
var existingTemplates = await templateService.Get()
.Where(t => t.JobId == jobId)
.ToListAsync();
logger.LogDebug("Для JobId {JobId} найдено {Count} существующих шаблонов.", jobId, existingTemplates.Count());
// 3. Получаем Job, чтобы получить маску имени
var job = await jobService.GetAsync(jobId);
if (job == null)
{
logger.LogError("Job с Id {JobId} не найден.", jobId);
return;
}
// 4. Находим UnitId, для которых нет шаблонов (нужно создать)
var existingUnitIds = existingTemplates.Select(t => t.UnitId).ToHashSet();
var unitIdsToCreate = expectedUnitIds.Except(existingUnitIds);
logger.LogDebug("Для JobId {JobId} найдено {Count} Unit'ов без шаблонов (требуется создание).", jobId, unitIdsToCreate.Count());
foreach (var unitId in unitIdsToCreate)
{
logger.LogInformation("Для UnitId {UnitId} нет шаблона, запрашиваем создание.", unitId);
var mqRequest = new TemplateGeneratorWorkerMq
{
JobId = jobId,
UnitId = unitId,
HistoryInitiator = initiator
};
var msg = JsonSerializer.Serialize(mqRequest);
var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg });
if (result.IsSuccess)
logger.LogInformation("Отправлен запрос на создание шаблона для UnitId {UnitId} в JobId {JobId}", unitId, jobId);
else
logger.LogError("Ошибка при отправке запроса на создание шаблона для UnitId {UnitId} в JobId {JobId}: {Message}", unitId, jobId, msg);
}
// 5. Находим шаблоны, которые больше не соответствуют фильтрам (нужно отключить/обновить)
var unitIdsToRemove = existingUnitIds.Except(expectedUnitIds);
logger.LogDebug("Для JobId {JobId} найдено {Count} Unit'ов с шаблонами, которые больше не соответствуют фильтрам (требуется обновление/отключение).", jobId, unitIdsToRemove.Count());
foreach (var template in existingTemplates)
{
var unitId = template.UnitId;
if (unitIdsToRemove.Contains(template.UnitId))
{
logger.LogInformation("Шаблон {TemplateId} для UnitId {UnitId} больше не соответствует фильтрам Job. Требуется обновление статуса.", template.Id, template.UnitId);
// 1. Меняем статус
template.StatusTypeId = TemplateStatusTypeEnum.Updating;
// 2. Сохраняем изменения в базе через сервис
var saved = await templateService.CommitAsync(initiator);
if (!saved)
{
logger.LogError(null, "Не удалось сохранить изменения шаблона {TemplateId} перед отправкой в очередь обновления.", template.Id);
continue; // пропускаем этот шаблон
}
// 3. Подготовим сообщение
var updateRequest = new TemplateUpdaterMq
{
TemplateId = template.Id,
JobId = template.JobId,
Name = await shortcodesService.ApplyShortcodesAsync(job.TemplateNameMask, template.UnitId, jobId),
IsActiveTemplate = template.IsActiveTemplate,
IsActiveSchedule = false,
LastRun = template.LastRun,
NextRun = template.NextRun,
UnitId = template.UnitId,
Index = template.Index,
StatusTypeId = TemplateStatusTypeEnum.Unused, // после обновления статус должен быть Unused
Initiator = initiator
};
// 4. Отправляем в очередь
await SendTemplateUpdateMessage(updateRequest);
}
else
{
// Unit всё ещё соответствует фильтрам — проверим, нужно ли обновить имя
logger.LogDebug("Шаблон {TemplateId} для UnitId {UnitId} соответствует фильтрам. Проверяем имя.", template.Id, unitId);
await CheckAndSendNameUpdateIfRequired(template, job, initiator);
}
}
logger.LogDebug("Окончание синхронизации шаблонов для JobId {JobId}", jobId);
}
public async Task UpdateTemplatesForJob(Guid jobId, HistoryInitiator initiator)
{
logger.LogDebug("Начало обновления имён шаблонов для JobId {JobId}", jobId);
// 1. Получаем все шаблоны для этого Job
var existingTemplates = await templateService.Get()
.Where(t => t.JobId == jobId)
.ToListAsync();
logger.LogDebug("Для JobId {JobId} найдено {Count} существующих шаблонов.", jobId, existingTemplates.Count());
if (!existingTemplates.Any())
{
logger.LogInformation("Для JobId {JobId} не найдено существующих шаблонов для обновления имени.", jobId);
return;
}
// 2. Получаем Job, чтобы получить маску имени
var job = await jobService.GetAsync(jobId);
if (job == null)
{
logger.LogError("Job с Id {JobId} не найден.", jobId);
return;
}
foreach (var template in existingTemplates)
{
logger.LogDebug("Проверяем имя шаблона {TemplateId} для UnitId {UnitId}.", template.Id, template.UnitId);
// Проверяем, нужно ли обновить имя
await CheckAndSendNameUpdateIfRequired(template, job, initiator);
}
logger.LogDebug("Окончание обновления имён шаблонов для JobId {JobId}", jobId);
}
private async Task CheckAndSendNameUpdateIfRequired(Template template, Job job, HistoryInitiator initiator)
{
var expectedName = await shortcodesService.ApplyShortcodesAsync(job.TemplateNameMask, template.UnitId, job.Id);
logger.LogDebug("Шаблон {TemplateId}: текущее имя '{CurrentName}', ожидаемое имя '{ExpectedName}'", template.Id, template.Name, expectedName);
if (template.Name != expectedName)
{
logger.LogInformation("Шаблон {TemplateId} для UnitId {UnitId} имеет устаревшее имя. Требуется обновление.", template.Id, template.UnitId);
// 1. Меняем статус в шаблоне
template.StatusTypeId = TemplateStatusTypeEnum.Updating;
// 2. Сохраняем изменения в базе через сервис
var saved = await templateService.CommitAsync(initiator);
if (!saved)
{
logger.LogError("Не удалось сохранить изменения шаблона {TemplateId} перед отправкой в очередь обновления.", template.Id);
return; // не отправляем сообщение, если не сохранили
}
// 3. Подготовим сообщение для отправки в очередь
var updateRequest = new TemplateUpdaterMq
{
TemplateId = template.Id,
JobId = template.JobId,
Name = expectedName,
IsActiveTemplate = template.IsActiveTemplate,
IsActiveSchedule = template.IsActiveSchedule,
LastRun = template.LastRun,
NextRun = template.NextRun,
UnitId = template.UnitId,
Index = template.Index,
StatusTypeId = TemplateStatusTypeEnum.Used,
Initiator = initiator
};
// 4. Отправляем в очередь
await SendTemplateUpdateMessage(updateRequest);
}
else
{
logger.LogDebug("Шаблон {TemplateId} для UnitId {UnitId} имеет актуальное имя.", template.Id, template.UnitId);
}
}
private async Task SendTemplateUpdateMessage(TemplateUpdaterMq updateRequest)
{
logger.LogDebug("Отправка сообщения в очередь '{Queue}' для шаблона {TemplateId}",
mqSettings.TemplateUpdater.QueueName, updateRequest.TemplateId);
var msg = JsonSerializer.Serialize(updateRequest);
var result = await mqService.SendAsync(mqSettings.TemplateUpdater, new[] { msg });
if (result.IsSuccess)
{
logger.LogInformation("Отправлен запрос на обновление шаблона {TemplateId}", updateRequest.TemplateId);
}
else
{
logger.LogError("Ошибка при отправке запроса на обновление шаблона {TemplateId}: {Message}",
updateRequest.TemplateId, msg);
}
}
}
}