Files
parr_api/PARR.GeneratorTemplates/Services/TemplateManager.cs

329 lines
18 KiB
C#
Raw Normal View History

2023-09-22 15:30:57 +10:00
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Helpers;
using PARR.Constants;
2023-09-22 15:30:57 +10:00
using PARR.DAL.Contracts;
using PARR.DAL.Extensions;
using PARR.DAL.Models;
2023-09-22 15:30:57 +10:00
using PARR.DAL.Services.Interfaces;
using PARR.TemplateDistributor;
using System.Text.Json;
2023-09-22 15:30:57 +10:00
namespace PARR.GeneratorTemplates.Services
{
internal class TemplateManager : ITemplateManager
{
private readonly ITemplateService templateService;
private readonly IHostService hostService;
2023-09-22 15:30:57 +10:00
private readonly ILogger<TemplateManager> logger;
private readonly SettingsFromDb settingsFromDb;
private readonly IRobotConfigurationService robotConfigurationService;
private readonly IApplicationsInWorkService applicationsInWorkService;
private readonly ITemplateDistributor templateDistributor;
2023-09-22 15:30:57 +10:00
public TemplateManager(
ITemplateService templateService,
IHostService hostService,
ILogger<TemplateManager> logger,
SettingsFromDb settingsFromDb,
IRobotConfigurationService robotConfigurationService,
IApplicationsInWorkService applicationsInWorkService,
ITemplateDistributor templateDistributor
2023-09-22 15:30:57 +10:00
)
{
this.templateService = templateService;
this.hostService = hostService;
2023-09-22 15:30:57 +10:00
this.logger = logger;
this.settingsFromDb = settingsFromDb;
this.robotConfigurationService = robotConfigurationService;
this.applicationsInWorkService = applicationsInWorkService;
this.templateDistributor = templateDistributor;
2023-09-22 15:30:57 +10:00
}
public async Task CreateTemplates(GeneratorTemplateMq query)
{
//TODO Migratin to Job
////В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты
//var appInWorkWg = await applicationsInWorkService.Get()
// .Include(t => t.WorkGroups)
// .FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId);
//if (!appInWorkWg.WorkGroups.Any())
//{
// logger.LogWarning($"Не генерирую шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}");
// return;
//}
//var workGroups = appInWorkWg.WorkGroups.ToList();
////Согласно параметрам, находит все ЭК в таблице Hosts.
////Далее проверяет есть ли такие шаблоны в таблице Templates, если нет, то создает, активирует и ставит статус Creating.
////Если такие шаблоны уже есть, ничего с ними не делает.
//string ekPattern = SqlHelpers.RegexToLike(query.Ek);
//// список хостов для создания шаблонов
//var queryHosts = hostService.Get()
// //.Include(t => t.WorkGroupItem)
// .Include(t => t.ApplicationsInHosts)
// .ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationsInWorks).ThenInclude(w => w.Work)
// .Include(t => t.Templates)
// .ThenInclude(w => w.ApplicationsInWork)
// .Include(t => t.ResponseArea)
// .Where(t =>
// t.ApplicationsInHosts.Any(h =>
// h.ApplicationId == query.ApplicationId
// && h.Application!.ApplicationsInWorks.Any(w => w.WorkId == query.WorkId)
// )
// && EF.Functions.Like(t.Ek.ToLower(), ekPattern)
// // смотрим что нет такого шаблона
// && t.Templates.Any(templ => templ.ApplicationsInWork!.WorkId == query.WorkId && templ.ApplicationsInWork.ApplicationId == query.ApplicationId) == false
// // смотрим что у этих хостов есть нужные группы
// //&& workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)
// );
//// статус ЭК
//if (query.StatusEk > 0)
// queryHosts = queryHosts.Where(t => t.EkStatusCode == query.StatusEk);
//var hosts = await queryHosts
// .AsSplitQuery()
// .ToListAsync();
//// Исключаем хосты у которых нет нужных групп
//hosts = hosts.Where(t => workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)).ToList();
//if (!hosts.Any())
//{
// logger.LogInformation($"Не найдено ЭК попадающих под условие: ${JsonSerializer.Serialize(query)}");
// return;
//}
//// хосты группируем по РГ, чтоб потом распределить/рассчитать NextRun
//var groupingHostByWg = hosts.GroupBy(t => t.WorkGroupId);
//foreach (var group in groupingHostByWg)
//{
// var groupingHosts = group.ToList();
// var templates = CreateQueryTemplates(groupingHosts, query);
// //проверяем, что нет шаблонов с такими именами, исключаем их
// templates = await ExcludeExistTemplatesAsync(templates);
// if (!templates.Any())
// continue;
// //заполняем NextRun
// templates = await templateDistributor.DistributeTemplateAsync(templates, appInWorkWg.Id, (Guid)group.Key!);
// // сохраняем
// foreach (var template in templates)
// {
// if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync(query.HistoryInitiator))
// {
// logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}");
// }
// else
// {
// logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " +
// $"HostId: {template.HostId}");
// }
// }
//}
#region создавали шаблоны до того, как стали группировать по РГ
////Создаем шаблоны
//foreach (var host in hosts)
//{
// var appInWork = host.ApplicationsInHosts.FirstOrDefault(t => t.ApplicationId == query.ApplicationId)?.Application?.ApplicationsInWorks.FirstOrDefault(a => a.WorkId == query.WorkId);
// if (appInWork == null)
// {
// // такого не может быть, так как выполнился запрос при получении списка хостов, но мало ли
// logger.LogError($"Ошибка при создании шаблона. В таблице ApplicationsInWorks не найден Id согласно запроса WorkId: {query.WorkId}, ApplicationId: {query.ApplicationId}");
// return;
// }
// var template = new Template
// {
// Id = Guid.NewGuid(),
// //Name = TemplateHelpers.GenerateTemplateName("ЗО" ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name),
// //Генерить имя с полным именем работы и подстановкой ЭК
// //Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)),
// //Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
// Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(
// host.ResponseArea!.Name,
// settingsFromDb.TemplatePrefixName,
// host.Ek,
// appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)
// ),
// IsActiveTemplate = query.IsActiveTemplate ?? false,
// IsActiveSchedule = query.IsActiveSchedule ?? false,
// ApplicationInWorkId = appInWork.Id,
// HostId = host.Id,
// //TODO:
// //NextRun = ???,
// LastRun = null
// };
// if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync())
// {
// logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}");
// }
// else
// {
// logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " +
// $"HostId: {template.HostId}");
// }
//}
#endregion
}
/// <summary>
/// Исключаем существующие шаблоны из запроса на создание
/// </summary>
/// <param name="templates"></param>
/// <returns></returns>
private async Task<List<Template>> ExcludeExistTemplatesAsync(List<Template> templates)
{
// то ли костыль, то ли нет. Иногда попадают отфильтрованные шаблоны для создания, но они уже есть в БД. На всякий проверяем есть они или нет, и если есть, исключаем их из запроса.
// ищмем по имени такие шаблоны в БД и исключаем их
var existTemplates = await templateService.Get().Where(t => templates.Select(x => x.Name).Any(x => x == t.Name)).ToListAsync();
if (existTemplates.Any())
{
existTemplates.ForEach(item => logger.LogWarning($"Исключаем из запроса на создание шаблон, так как он уже есть в БД: {item.Name}"));
templates = templates.Where(t => !existTemplates.Any(x => x.Name == t.Name)).ToList();
}
return templates;
}
private List<Template> CreateQueryTemplates(List<Host> hosts, GeneratorTemplateMq query)
{
var templates = new List<Template>();
foreach (var host in hosts)
{
var appInWork = host.ApplicationsInHosts.FirstOrDefault(t => t.ApplicationId == query.ApplicationId)?.Application?.ApplicationsInWorks.FirstOrDefault(a => a.WorkId == query.WorkId);
if (appInWork == null)
{
// такого не может быть, так как выполнился запрос при получении списка хостов, но мало ли
logger.LogError($"Ошибка при создании шаблона. В таблице ApplicationsInWorks не найден Id согласно запроса WorkId: {query.WorkId}, ApplicationId: {query.ApplicationId}");
//return;
return templates;
}
var template = new Template
{
Id = Guid.NewGuid(),
//Name = TemplateHelpers.GenerateTemplateName("ЗО" ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name),
//Генерить имя с полным именем работы и подстановкой ЭК
//Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)),
//Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(
host.ResponseArea!.Name,
settingsFromDb.TemplatePrefixName,
host.Ek,
appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name
),
IsActiveTemplate = query.IsActiveTemplate ?? false,
IsActiveSchedule = query.IsActiveSchedule ?? false,
JobId = appInWork.Id,//TODO Migratin to Job
UnitId = host.Id,//TODO Migratin to Job
// NextRun не задаем значение, его рассчитаем позже
//NextRun = ???,
LastRun = null
};
templates.Add(template);
}
return templates;
2023-09-22 15:30:57 +10:00
}
2023-09-22 15:30:57 +10:00
public async Task DeactivateTemplates(GeneratorTemplateMq query)
{
//TODO: !!! тут не учитываются поля query.IsActiveTemplate, query.IsActiveSchedule, просто все деактивируется. !!!
//В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты
var appInWorkWg = await applicationsInWorkService.Get()
.Include(t => t.WorkGroups)
.FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId);
if (!appInWorkWg.WorkGroups.Any())
{
logger.LogWarning($"Не деактивируем шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}");
return;
}
var workGroups = appInWorkWg.WorkGroups.ToList();
2023-09-22 15:30:57 +10:00
//Ищет все активные шаблоны согласно параметрам в таблице Templates, и деактивирует их. Меняем на статус Updating
// делаем sql формат для like из запроса.
string ekPattern = SqlHelpers.RegexToLike(query.Ek);
2023-09-22 15:30:57 +10:00
var queryTemplates = templateService.Get()
.Include(t => t.Unit)//TODO Migratin to Job
.Include(t => t.Job)//TODO Migratin to Job
.Include(t => t.RobotConfigurations)
2023-09-22 15:30:57 +10:00
.Where(t =>
(t.IsActiveTemplate == true || t.IsActiveSchedule == true)
//&& t.ApplicationsInWork!.ApplicationId == query.ApplicationId//TODO Migratin to Job
//&& t.ApplicationsInWork!.WorkId == query.WorkId//TODO Migratin to Job
&& EF.Functions.Like(t.Unit!.Name.ToLower(), ekPattern)
);
// статус ЭК
if (query.StatusEk > 0)
queryTemplates = queryTemplates;//.Where(t => t.Unit!.BaseFields.Status == query.StatusEk);//TODO Migratin to Job
var existTemplates = await queryTemplates
.AsSplitQuery()
.ToListAsync();
2023-09-22 15:30:57 +10:00
// Исключаем хосты у которых нет нужных групп
existTemplates = existTemplates.Where(t => workGroups.Any(x => x.WorkGroup.Name == t.Unit.BaseFields.WorkGroup)).ToList();
2023-09-22 15:30:57 +10:00
if (!existTemplates.Any())
{
logger.LogInformation("Нет шаблонов для деактивации");
return;
}
existTemplates.ForEach(item =>
{
item.DateModified = DateTimeOffset.UtcNow;
if (item.IsActiveTemplate)
{
item.IsActiveTemplate = false;
//необходимо обновить шаблон
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, ref item);
robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, ref config);
}
if (item.IsActiveSchedule)
{
item.IsActiveSchedule = false;
//необходимо обновить расписание
var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.ScheduleOrder, ref item);
robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, ref config);
}
2023-09-22 15:30:57 +10:00
});
if (await templateService.CommitAsync(query.HistoryInitiator))
2023-09-22 15:30:57 +10:00
existTemplates.ForEach(item => logger.LogInformation($"Деактивирован шаблон: {item.Name}"));
else
existTemplates.ForEach(item => logger.LogError($"Ошибка при дактивации шаблона: {item.Name}"));
}
}
}