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

255 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;
using PARR.Domain.Entities;
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(TemplateUpdaterMq 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.LastRun = query.LastRun;
template.Index = query.Index;
template.StatusTypeId = query.StatusTypeId;
// === Обработка изменения состава UnitsInTemplate ===
var currentUnitIds = template.UnitsInTemplate.Select(u => u.UnitId).ToHashSet();
var newUnitIds = query.UnitsInTemplate.ToHashSet();
if (!currentUnitIds.SetEquals(newUnitIds))
{
// Удаляем старые связи
var toRemove = template.UnitsInTemplate
.Where(u => !newUnitIds.Contains(u.UnitId))
.ToList();
foreach (var item in toRemove)
template.UnitsInTemplate.Remove(item);
// Добавляем новые связи
var toAdd = newUnitIds.Except(currentUnitIds);
foreach (var unitId in toAdd)
{
template.UnitsInTemplate.Add(new UnitsInTemplate
{
TemplateId = template.Id,
UnitId = unitId,
DateCreated = DateTimeOffset.UtcNow
});
}
// Поскольку коллекция изменилась — шаблон считается изменённым
templateIsChanged = true;
}
//Для правильного расчета shortcod'ов в БД должны быть сохранены данные UnitInTemplates, JobId, UnitId и т.д.
if (templateIsChanged && !await templateService.CommitAsync(query.Initiator))
{
logger.LogError("Не удалось сохранить изменения в БД. {QueryType}: {Query}", nameof(TemplateUpdaterMq), 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;
}
// === конец обработки UnitsInTemplate ===
if (templateIsChanged)
{
// ставим задачу на обновление шаблона
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, template);
//robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, config);
robotConfigurationService.SetUpdateTaskStatusIfAllow(config);
logger.LogDebug("Для шаблона {TemplateId} устанавливаю статус {Status}", template.Id, RobotStatusEnum.Wait.ToString());
}
if (scheduleIsChanged)
{
// ставим задачу на обновление расписания
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.ScheduleOrder, template);
//robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, config);
robotConfigurationService.SetUpdateTaskStatusIfAllow(config);
logger.LogDebug("Для расписания {TemplateId} устанавливаю статус {Status}", template.Id, RobotStatusEnum.Wait.ToString());
}
if (!await templateService.CommitAsync(query.Initiator))
{
logger.LogError("Не удалось сохранить изменения в БД. {QueryType}: {Query}", nameof(TemplateUpdaterMq), 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(TemplateUpdaterMq 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;
}
}
}