Files
parr_api/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs

249 lines
11 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.Core.Extensions;
using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.Job;
using PARR.Core.Repositories.Interfaces.Unit;
using PARR.Core.Services.NextRunServices;
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
using PARR.Domain.Entities.Job;
using PARR.Domain.Enums;
namespace PARR.TemplateUpdater.Services
{
internal class TemplateUpdaterService : ITemplateUpdaterService
{
private readonly ILogger<TemplateUpdaterService> logger;
private readonly ITemplateRepository templateService;
private readonly IJobRepository jobService;
private readonly IUnitRepository unitService;
private readonly IRobotConfigurationRepository robotConfigurationService;
private readonly INextRunService nextRunService;
public TemplateUpdaterService(
ILogger<TemplateUpdaterService> logger,
ITemplateRepository templateService,
IJobRepository jobService,
IUnitRepository unitService,
IRobotConfigurationRepository robotConfigurationService,
INextRunService nextRunService
)
{
this.logger = logger;
this.templateService = templateService;
this.jobService = jobService;
this.unitService = unitService;
this.robotConfigurationService = robotConfigurationService;
this.nextRunService = nextRunService;
}
public async Task UpdateTemplateAsync(TemplateUpdaterMessage query)
{
var isValid = await IsValidAsync(query);
if (!isValid)
{
logger.LogError("Не валидны входные данные. Конец обработки сообщения {Query}", query.ToJson());
return;
}
var template = await templateService.Get()
.Include(t => t.RobotConfigurations)
.Include(t => t.UnitsInTemplate)
.AsSplitQuery()
.FirstOrDefaultAsync(t => t.Id == query.TemplateId);
if (template == null)
{
logger.LogError("Не найден шаблон с id {TemplateId}", query.TemplateId);
return;
}
var templateIsChanged = false;
var scheduleIsChanged = false;
if (template.Name != query.Name.Trim())
{
template.Name = query.Name.Trim();
templateIsChanged = true;
scheduleIsChanged = true;
}
if (template.JobId != query.JobId)
{
template.JobId = query.JobId;
templateIsChanged = true;
scheduleIsChanged = true;
}
if (template.IsActiveTemplate != query.IsActiveTemplate)
{
template.IsActiveTemplate = query.IsActiveTemplate;
templateIsChanged = true;
}
if (template.IsActiveSchedule != query.IsActiveSchedule)
{
template.IsActiveSchedule = query.IsActiveSchedule;
scheduleIsChanged = true;
}
if (template.UnitId != query.UnitId)
{
template.UnitId = query.UnitId;
templateIsChanged = true;
scheduleIsChanged = true;
}
template.Index = query.Index;
template.StatusTypeId = query.StatusTypeId;
// === Обработка изменения состава UnitsInTemplate ===
// Формируем HashSet пар (UnitId, UnitFieldValueId) для быстрого сравнения
var currentEntries = template.UnitsInTemplate
.Select(u => new UnitInTemplateMessage { UnitId = u.UnitId, UnitFieldValueId = u.UnitFieldValueId })
.ToHashSet();
var newEntries = query.UnitsInTemplate.ToHashSet();
if (!currentEntries.SetEquals(newEntries))
{
// Удаляем связи, которых нет в новом наборе
var toRemove = template.UnitsInTemplate
.Where(u => !newEntries.Contains(new UnitInTemplateMessage { UnitId = u.UnitId, UnitFieldValueId = u.UnitFieldValueId }))
.ToList();
foreach (var item in toRemove)
template.UnitsInTemplate.Remove(item);
// Добавляем новые связи
var toAdd = newEntries.Except(currentEntries);
foreach (var entry in toAdd)
{
template.UnitsInTemplate.Add(new UnitsInTemplate
{
TemplateId = template.Id,
UnitId = entry.UnitId,
UnitFieldValueId = entry.UnitFieldValueId,
DateCreated = DateTimeOffset.UtcNow
});
}
templateIsChanged = true;
}
// === Конец обработки UnitsInTemplate ===
// Для правильного расчета shortcod'ов в БД должны быть сохранены данные UnitsInTemplate, JobId, UnitId и т.д.
if (templateIsChanged && !await templateService.CommitAsync(query.Initiator))
{
logger.LogError("Не удалось сохранить изменения в БД. {QueryType}: {Query}", nameof(TemplateUpdaterMessage), query.ToJson());
return;
}
var nextRun = await nextRunService.GetNextRunForTemplateAsync(template.Id, query.IsNew);
if (!nextRun.HasValue)
{
logger.LogError("Ошибка при расчете нового nextRun (вернулся null) для шаблона {TemplateId}, {TemplateName}", template.Id, template.Name);
return;
}
if (template.NextRun != nextRun.Value)
{
template.LastRun = template.NextRun;
template.NextRun = nextRun.Value;
scheduleIsChanged = true;
}
if (templateIsChanged)
{
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, template);
robotConfigurationService.SetUpdateTaskStatusIfAllow(config);
logger.LogDebug("Для шаблона {TemplateId} устанавливаю статус {Status}", template.Id, RobotStatusEnum.Wait.ToString());
}
if (scheduleIsChanged)
{
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.ScheduleOrder, template);
robotConfigurationService.SetUpdateTaskStatusIfAllow(config);
logger.LogDebug("Для расписания {TemplateId} устанавливаю статус {Status}", template.Id, RobotStatusEnum.Wait.ToString());
}
if (!await templateService.CommitAsync(query.Initiator))
{
logger.LogError("Не удалось сохранить изменения в БД. {QueryType}: {Query}", nameof(TemplateUpdaterMessage), query.ToJson());
return;
}
logger.LogInformation("Выполнено изменение шаблона в БД. Отправлен запрос на синхронизацию шаблона: {TemplateIsChanged}, расписания: {ScheduleIsChanged}. Query {Query}", templateIsChanged, scheduleIsChanged, query.ToJson());
}
/// <summary>
/// Валидация входящего сообщения
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
private async Task<bool> IsValidAsync(TemplateUpdaterMessage query)
{
var template = await templateService.Get().AsNoTracking()
.Include(t => t.RobotConfigurations)
.FirstOrDefaultAsync(t => t.Id == query.TemplateId);
if (template == null)
{
logger.LogError("Сообщение не валидно. Не найден шаблон с id: {TemplateId}", query.TemplateId);
return false;
}
//if (template.ScheduleEsppId == null)
//{
// logger.LogError("Сообщение не валидно. Номер расписания не может быть null, робот не сможет обновить шаблон: {TemplateName}", template.Name);
// return false;
//}
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, template);
if (config == null)
{
logger.LogError("Сообщение не валидно. Не создана конфигурация роботов: {TemplateName}", template.Name);
return false;
}
//if (config.TaskStatusCode != (int)TaskStatusEnum.Ok)
//{
// logger.LogError("Сообщение не валидно. Не закончено создание или предыдущее обновление - нельзя начинать новое изменение шаблона: {TemplateName}", template.Name);
// return false;
//}
if (string.IsNullOrEmpty(query.Name?.Trim()))
{
logger.LogError("Сообщение не валидно. Имя шаблона не может быть пустым: {TemplateName}", query.Name);
return false;
}
var existTemplateName = await templateService.Get().AsNoTracking().AnyAsync(t =>
t.Id != query.TemplateId
&& t.Name!.ToUpper() == query.Name.Trim().ToUpper()
&& t.Index == query.Index);
if (existTemplateName)
{
logger.LogError("Сообщение не валидно. Имя шаблона не уникально: {TemplateName}", query.Name);
return false;
}
var job = await jobService.Get().AsNoTracking().AnyAsync(t => t.Id == query.JobId);
if (!job)
{
logger.LogError("Сообщение не валидно. Не найдена работа с JobId: {JobId}", query.JobId);
return false;
}
var unit = await unitService.Get().AsNoTracking().AnyAsync(t => t.Id == query.UnitId);
if (!unit)
{
logger.LogError("Сообщение не валидно. Не найден unit с UnitId: {UnitId}", query.UnitId);
return false;
}
return true;
}
}
}