# Conflicts:
#	PARR.TemplateDistributor/TemplateDistributor.cs
This commit is contained in:
Mikhail Kuznetsov
2024-07-05 15:21:06 +10:00
28 changed files with 462 additions and 81 deletions

View File

@@ -356,6 +356,16 @@
#endregion #endregion
#region Distributor
public static class Distributor
{
public const string Distribute = Base + "/distributor/";
}
#endregion
} }
} }

View File

@@ -15,7 +15,17 @@
public required string Solution { get; set; } public required string Solution { get; set; }
public DateTimeOffset NextRun { get; set; } //public DateTimeOffset NextRun { get; set; }
/// <summary>
/// Дата начала работ
/// </summary>
public DateTimeOffset ReferenceDate { get; set; }
/// <summary>
/// Включить автораспределение
/// </summary>
public bool IsAutoDistributionEnabled { get; set; }
public bool IsAgent { get; set; } public bool IsAgent { get; set; }

View File

@@ -0,0 +1,7 @@
namespace PARR.API.Contracts.V1.Requests
{
public class DistributeRequest
{
public Guid ApplicationInWorkId { get; set; }
}
}

View File

@@ -12,9 +12,13 @@
public required string Solution { get; set; } public required string Solution { get; set; }
public DateTimeOffset? LastRun { get; set; } //public DateTimeOffset? LastRun { get; set; }
public DateTimeOffset NextRun { get; set; } //public DateTimeOffset NextRun { get; set; }
public DateTimeOffset ReferenceDate { get; set; }
public bool IsAutoDistributionEnabled { get; set; }
public bool IsAgent { get; set; } public bool IsAgent { get; set; }
@@ -32,7 +36,7 @@
public ApplicationInWorkScheduleResponse? Schedule { get; set; } public ApplicationInWorkScheduleResponse? Schedule { get; set; }
public List<WorkGroupResponse>? WorkGroups { get; set; } public List<WorkGroupResponse>? WorkGroups { get; set; }
} }

View File

@@ -57,6 +57,8 @@
public Guid Id { get; set; } public Guid Id { get; set; }
public required string Value { get; set; } public required string Value { get; set; }
public Guid? DistributionPeriodId { get; set; }
} }
public class EsppScheduleTypeConfigWithDataResponse public class EsppScheduleTypeConfigWithDataResponse

View File

@@ -23,6 +23,7 @@
public DateTimeOffset? LastRun { get; set; } public DateTimeOffset? LastRun { get; set; }
public DateTimeOffset NextRun { get; set; } public DateTimeOffset NextRun { get; set; }
public bool IsAutoDistributionEnabled { get; set; }
public HostTemplateResponse? Host { get; set; } public HostTemplateResponse? Host { get; set; }

View File

@@ -71,7 +71,8 @@ namespace PARR.API.Controllers.V1
&& t.ApplicationsInWork!.IsAgent == true && t.ApplicationsInWork!.IsAgent == true
&& t.IsActiveTemplate == true && t.IsActiveTemplate == true
&& t.IsActiveSchedule == true && t.IsActiveSchedule == true
&& t.ApplicationsInWork!.NextRun.DateTime.Date == date.Date.Date //&& t.ApplicationsInWork!.NextRun.DateTime.Date == date.Date.Date
&& t.NextRun.DateTime.Date == date.Date.Date
&& t.RobotConfigurations.All(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok) && t.RobotConfigurations.All(c => c.TaskStatusCode == (int)TaskStatusEnum.Ok)
&& t.ApplicationsInWork.EsppSchValues.Any() && t.ApplicationsInWork.EsppSchValues.Any()
).ToListAsync(); ).ToListAsync();
@@ -87,12 +88,12 @@ namespace PARR.API.Controllers.V1
foreach (var template in templates) foreach (var template in templates)
{ {
//var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.LastRun ?? template.ApplicationsInWork!.NextRun); //var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.LastRun ?? template.ApplicationsInWork!.NextRun);
var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.ApplicationsInWork!.NextRun); var templateSchedule = await esppScheduleTransformService.GetNextScheduleAsync(template.ApplicationInWorkId, template.NextRun);
if (!templateSchedule.Any()) if (!templateSchedule.Any())
{ {
logger.LogWarning($"Запросили раписание для агента по NextRun и вернулся пустой список! Такого не должно быть! " + logger.LogWarning($"Запросили раписание для агента по NextRun и вернулся пустой список! Такого не должно быть! " +
$"ApplicationInWorkId: {template.ApplicationInWorkId}, latRun: {template.ApplicationsInWork!.LastRun}, NextRun: {template.ApplicationsInWork!.NextRun}, ip: {ip}, date: {date}"); $"ApplicationInWorkId: {template.ApplicationInWorkId}, latRun: {template.LastRun}, NextRun: {template.NextRun}, ip: {ip}, date: {date}");
continue; continue;
} }

View File

@@ -11,10 +11,14 @@ using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Controllers.V1.Base; using PARR.API.Controllers.V1.Base;
using PARR.API.Extensions; using PARR.API.Extensions;
using PARR.API.Services.Interfaces; using PARR.API.Services.Interfaces;
using PARR.API.Settings;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.DomainModels; using PARR.DAL.DomainModels;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using System.Text.Json;
namespace PARR.API.Controllers.V1 namespace PARR.API.Controllers.V1
{ {
@@ -27,6 +31,8 @@ namespace PARR.API.Controllers.V1
private readonly IValidator<ApplicationInWorkRequest> validator; private readonly IValidator<ApplicationInWorkRequest> validator;
private readonly IUriService uriService; private readonly IUriService uriService;
private readonly ITemplateService templateService; private readonly ITemplateService templateService;
private readonly IMqService mqService;
private readonly MqSettings mqSettings;
public ApplicationInWorkController( public ApplicationInWorkController(
ILogger<ApplicationInWorkController> logger, ILogger<ApplicationInWorkController> logger,
@@ -34,7 +40,9 @@ namespace PARR.API.Controllers.V1
IApplicationsInWorkService applicationsInWorkService, IApplicationsInWorkService applicationsInWorkService,
IValidator<ApplicationInWorkRequest> validator, IValidator<ApplicationInWorkRequest> validator,
IUriService uriService, IUriService uriService,
ITemplateService templateService ITemplateService templateService,
IMqService mqService,
MqSettings mqSettings
) )
{ {
this.logger = logger; this.logger = logger;
@@ -43,6 +51,8 @@ namespace PARR.API.Controllers.V1
this.validator = validator; this.validator = validator;
this.uriService = uriService; this.uriService = uriService;
this.templateService = templateService; this.templateService = templateService;
this.mqService = mqService;
this.mqSettings = mqSettings;
} }
@@ -147,7 +157,9 @@ namespace PARR.API.Controllers.V1
ShortDescription = request.ShortDescription.Trim(), ShortDescription = request.ShortDescription.Trim(),
FullDescription = request.FullDescription.Trim(), FullDescription = request.FullDescription.Trim(),
Solution = request.Solution.Trim(), Solution = request.Solution.Trim(),
NextRun = request.NextRun, //NextRun = request.NextRun,
IsAutoDistributionEnabled = request.IsAutoDistributionEnabled,
ReferenceDate = request.ReferenceDate,
IsAgent = request.IsAgent, IsAgent = request.IsAgent,
AgentName = request.AgentName?.Trim(), AgentName = request.AgentName?.Trim(),
AgentTimeOutSec = request.AgentTimeOutSec, AgentTimeOutSec = request.AgentTimeOutSec,
@@ -178,7 +190,7 @@ namespace PARR.API.Controllers.V1
if (!await applicationsInWorkService.CreateAsync(applicationInWork) || !await applicationsInWorkService.CommitAsync()) if (!await applicationsInWorkService.CreateAsync(applicationInWork) || !await applicationsInWorkService.CommitAsync())
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при созании задания на выполнение работ" } })); return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при созании задания на выполнение работ" } }));
logger.LogInformation($"Пользователь {User.Identity?.Name} добавил задание на выполнение работ: {applicationInWork.Id}, {applicationInWork.ShortDescription}, {applicationInWork.Solution}, {applicationInWork.NextRun}"); logger.LogInformation($"Пользователь {User.Identity?.Name} добавил задание на выполнение работ: {applicationInWork.Id}, {applicationInWork.ShortDescription}, {applicationInWork.Solution}");
var createdApplicationInWork = await applicationsInWorkService.Get() var createdApplicationInWork = await applicationsInWorkService.Get()
@@ -225,13 +237,18 @@ namespace PARR.API.Controllers.V1
if (orig == null) if (orig == null)
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } })); return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } }));
//Расписание было изменено, ниже добавим задание в очередь на обновление расписаний у связанных шаблонов
var isScheduleChanged = IsScheduleChanged(orig, request);
orig.WorkId = request.WorkId; orig.WorkId = request.WorkId;
orig.ApplicationId = request.ApplicationId; orig.ApplicationId = request.ApplicationId;
orig.TemplateDuration = request.TemplateDuration; orig.TemplateDuration = request.TemplateDuration;
orig.ShortDescription = request.ShortDescription.Trim(); orig.ShortDescription = request.ShortDescription.Trim();
orig.FullDescription = request.FullDescription.Trim(); orig.FullDescription = request.FullDescription.Trim();
orig.Solution = request.Solution.Trim(); orig.Solution = request.Solution.Trim();
orig.NextRun = request.NextRun; //orig.NextRun = request.NextRun;
orig.ReferenceDate = request.ReferenceDate;
orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled;
orig.IsAgent = request.IsAgent; orig.IsAgent = request.IsAgent;
orig.AgentName = request.AgentName?.Trim(); orig.AgentName = request.AgentName?.Trim();
orig.AgentTimeOutSec = request.AgentTimeOutSec; orig.AgentTimeOutSec = request.AgentTimeOutSec;
@@ -267,9 +284,29 @@ namespace PARR.API.Controllers.V1
logger.LogInformation($"Пользователь {User.Identity?.Name} обновил задание на выполнение работ: {orig.Id}," + logger.LogInformation($"Пользователь {User.Identity?.Name} обновил задание на выполнение работ: {orig.Id}," +
$" {orig.WorkId}, {orig.ApplicationId}, {orig.TemplateDuration}, {orig.ShortDescription}," + $" {orig.WorkId}, {orig.ApplicationId}, {orig.TemplateDuration}, {orig.ShortDescription}," +
$" {orig.FullDescription}, {orig.Solution}, {orig.NextRun}, {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}"); $" {orig.FullDescription}, {orig.Solution}, {nameof(orig.IsAutoDistributionEnabled)}: {orig.IsAutoDistributionEnabled}, {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}");
if (isScheduleChanged)
{
//расписание было обновлено, отправим задание в очередь на перерасчет NextRun
var requestToMq = new TemplateDistributorMq
{
ApplicationInWorkId = id
};
var msg = JsonSerializer.Serialize(requestToMq);
logger.LogDebug($"Расписание в РР applicationInWorkId: {id} было изменено. Отправляем задание в очередь на перерасчет NextRun");
var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg });
if (sendResult.IsSuccess)
logger.LogInformation($"Задание на перерасчет NextRun успешно отправлено в очередь MQ {mqSettings.TemplateDistributor.QueueName}");
else
logger.LogError($"Ошибка при отправке задания на перерасчет NextRun в очередь MQ {mqSettings.TemplateDistributor.QueueName}");
}
var updatedApplicationInWork = await applicationsInWorkService.Get() var updatedApplicationInWork = await applicationsInWorkService.Get()
.Include(t => t.Application).ThenInclude(t => t!.ApplicationType) .Include(t => t.Application).ThenInclude(t => t!.ApplicationType)
.Include(t => t.Work) .Include(t => t.Work)
@@ -317,10 +354,40 @@ namespace PARR.API.Controllers.V1
logger.LogInformation($"Пользователь {User.Identity?.Name} удалил задание на выполнение работ: {applicationsInWork.Id},{applicationsInWork.WorkId}," + logger.LogInformation($"Пользователь {User.Identity?.Name} удалил задание на выполнение работ: {applicationsInWork.Id},{applicationsInWork.WorkId}," +
$" {applicationsInWork.ApplicationId}, {applicationsInWork.TemplateDuration}, {applicationsInWork.ShortDescription}," + $" {applicationsInWork.ApplicationId}, {applicationsInWork.TemplateDuration}, {applicationsInWork.ShortDescription}," +
$" {applicationsInWork.FullDescription}, {applicationsInWork.Solution}, {applicationsInWork.NextRun}, {applicationsInWork.IsAgent}," + $" {applicationsInWork.FullDescription}, {applicationsInWork.Solution}, {nameof(applicationsInWork.IsAutoDistributionEnabled)}: {applicationsInWork.IsAutoDistributionEnabled}, {applicationsInWork.IsAgent}," +
$" {applicationsInWork.AgentName}, {applicationsInWork.AgentTimeOutSec}, {applicationsInWork.AgentScript}"); $" {applicationsInWork.AgentName}, {applicationsInWork.AgentTimeOutSec}, {applicationsInWork.AgentScript}");
return NoContent(); return NoContent();
} }
/// <summary>
/// Проверка, были ли изменения в расписании
/// </summary>
/// <param name="orig"></param>
/// <param name="request"></param>
/// <returns></returns>
private bool IsScheduleChanged(ApplicationsInWork orig, ApplicationInWorkRequest request)
{
var isScheduleChanged = false;
if (orig.ReferenceDate != request.ReferenceDate)
isScheduleChanged = true;
if (request.Schedule.Count() != orig.EsppSchValues.Count())
isScheduleChanged = true;
request.Schedule.ForEach(requestSchedule =>
{
var schExist = orig.EsppSchValues.FirstOrDefault(t => t.ApplicationsInWorkId == orig.Id
&& t.TypeValueId == requestSchedule.TypeValueId
&& t.TypeConfigId == requestSchedule.TypeConfigId);
if (schExist == null)
isScheduleChanged = true;
});
return isScheduleChanged;
}
} }
} }

View File

@@ -0,0 +1,65 @@
using FluentValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Controllers.V1.Base;
using PARR.API.Settings;
using PARR.BLL.Domain.Mq;
using PARR.BLL.Services.Interfaces;
using PARR.Constants;
using System.Text.Json;
namespace PARR.API.Controllers.V1
{
/// <summary>
/// Распределитель РР
/// </summary>
[Authorize(Roles = ParrRoles.Administrator.Role)]
public class DistributorController : BaseApiController
{
private readonly IMqService mqService;
private readonly MqSettings mqSettings;
private readonly IValidator<DistributeRequest> validator;
public DistributorController(
IMqService mqService,
MqSettings mqSettings,
IValidator<DistributeRequest> validator
)
{
this.mqService = mqService;
this.mqSettings = mqSettings;
this.validator = validator;
}
/// <summary>
/// Перераспределить шаблоны для регламентной работы
/// </summary>
/// <returns></returns>
[HttpPost(ApiRoutes.Distributor.Distribute)]
public async Task<IActionResult> Distribute([FromBody] DistributeRequest request)
{
var resultValidate = await validator.ValidateAsync(request);
if (!resultValidate.IsValid)
return BadRequest(new Response(resultValidate.Errors));
var requestToMq = new TemplateDistributorMq
{
ApplicationInWorkId = request.ApplicationInWorkId
};
var msg = JsonSerializer.Serialize(requestToMq);
var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg });
if (sendResult.IsSuccess)
return Created("", new Response<string?>(null, true, new List<ErrorModel>(), "Отправлен запрос на перераспределение регламентных работ."));
else
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message="Ошибка при отправке данных."} }));
}
}
}

View File

@@ -143,35 +143,52 @@ namespace PARR.API.Controllers.V1
private async Task UpdateLastNextRunDate(RobotConfiguration task) private async Task UpdateLastNextRunDate(RobotConfiguration task)
{ {
var appInWorks = task.Template!.ApplicationsInWork!; var template = task.Template!;
// передаем LastRun, если его нет, то NextRun // передаем LastRun, если его нет, то NextRun
//var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun); //var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun);
// всегда считаем по nextRun // всегда считаем по nextRun
var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.NextRun); var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.ApplicationInWorkId, template.NextRun);
if (nextRun != appInWorks.NextRun) if (nextRun != template.NextRun)
{ {
logger.LogDebug($"Для appilcationInWork id {task.Template.ApplicationInWorkId}, шаблона id {task.TemplateId} обновляю nextRun, новое значение {nextRun}, старое значение {appInWorks.NextRun}"); logger.LogDebug($"Для шаблона id {template.Id} обновляю nextRun, новое значение {nextRun}, старое значение {template.NextRun}");
if (appInWorks.NextRun < DateTimeOffset.UtcNow) if (template.NextRun < DateTimeOffset.UtcNow)
{ {
logger.LogDebug($"Для appilcationInWork id {task.Template.ApplicationInWorkId}, шаблона id {task.TemplateId} обновляю lastRun, новое значение {appInWorks.NextRun}, старое значение {appInWorks.LastRun}"); logger.LogDebug($"Для шаблона id {template.Id} обновляю lastRun, новое значение {template.NextRun}, старое значение {template.LastRun}");
appInWorks.LastRun = appInWorks.NextRun; template.LastRun = template.NextRun;
} }
appInWorks.NextRun = nextRun; template.NextRun = nextRun;
await robotConfigurationService.CommitAsync(); await robotConfigurationService.CommitAsync();
} }
//if (appInWorks.LastRun != null) // if - ерунда какая-то. ошибка видимо. #region Old, до выноса lastRun, nextRun в templates
//if (nextRun > DateTimeOffset.UtcNow) //var appInWorks = task.Template!.ApplicationsInWork!;
// appInWorks.LastRun = appInWorks.NextRun;
//appInWorks.NextRun = nextRun; //// передаем LastRun, если его нет, то NextRun
////var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.LastRun ?? task.Template.ApplicationsInWork.NextRun);
//// всегда считаем по nextRun
//var nextRun = await esppScheduleTransformService.GetNextDateAsync(task.Template!.ApplicationInWorkId, task.Template.ApplicationsInWork!.NextRun);
//if (nextRun != appInWorks.NextRun)
//{
// logger.LogDebug($"Для appilcationInWork id {task.Template.ApplicationInWorkId}, шаблона id {task.TemplateId} обновляю nextRun, новое значение {nextRun}, старое значение {appInWorks.NextRun}");
// if (appInWorks.NextRun < DateTimeOffset.UtcNow)
// {
// logger.LogDebug($"Для appilcationInWork id {task.Template.ApplicationInWorkId}, шаблона id {task.TemplateId} обновляю lastRun, новое значение {appInWorks.NextRun}, старое значение {appInWorks.LastRun}");
// appInWorks.LastRun = appInWorks.NextRun;
// }
// appInWorks.NextRun = nextRun;
// await robotConfigurationService.CommitAsync();
//}
#endregion
//await robotConfigurationService.CommitAsync();
} }
} }
} }

View File

@@ -33,9 +33,12 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.SyncStatus, o => o.MapFrom(s => s.RobotConfigurations.OrderBy(t => t.RobotCode))) .ForMember(d => d.SyncStatus, o => o.MapFrom(s => s.RobotConfigurations.OrderBy(t => t.RobotCode)))
.ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>()) .ForMember(d => d.Schedule, o => o.MapFrom<TemplateScheduleResolver>())
.ForMember(d => d.Agent, o => o.MapFrom(s => s.ApplicationsInWork)) .ForMember(d => d.Agent, o => o.MapFrom(s => s.ApplicationsInWork))
.ForMember(d => d.NextRun, o => o.MapFrom(s => s.ApplicationsInWork!.NextRun)) //.ForMember(d => d.NextRun, o => o.MapFrom(s => s.ApplicationsInWork!.NextRun))
.ForMember(d => d.LastRun, o => o.MapFrom(s => s.ApplicationsInWork!.LastRun)) //.ForMember(d => d.LastRun, o => o.MapFrom(s => s.ApplicationsInWork!.LastRun))
.ForMember(d => d.OrderCount, o => o.MapFrom(s => s.Orders.Count())); .ForMember(d => d.NextRun, o => o.MapFrom(s => s.NextRun))
.ForMember(d => d.LastRun, o => o.MapFrom(s => s.LastRun))
.ForMember(d => d.OrderCount, o => o.MapFrom(s => s.Orders.Count()))
.ForMember(d=>d.IsAutoDistributionEnabled, o=>o.MapFrom(s=>s.ApplicationsInWork!.IsAutoDistributionEnabled));
// === Template === // === Template ===
@@ -166,8 +169,12 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.Timezone, o => o.MapFrom<RobotTaskScheduleTimezoneResolver>()) .ForMember(d => d.Timezone, o => o.MapFrom<RobotTaskScheduleTimezoneResolver>())
.ForMember(d => d.RepeatRange, o => o.MapFrom<RobotTaskScheduleRepeatRangeResolver>()) .ForMember(d => d.RepeatRange, o => o.MapFrom<RobotTaskScheduleRepeatRangeResolver>())
//.ForMember(d => d.GenerationTime, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.ScheduleGenerationTime)) //.ForMember(d => d.GenerationTime, o => o.MapFrom(s => s.Template!.ApplicationsInWork!.ScheduleGenerationTime))
.ForMember(d => d.GenerationTime, o => o.MapFrom(s => EsppScheduleHelpers.GetGenerationTime(s.Template!.ApplicationsInWork!.NextRun))) //~~~~~~~~~
.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextRun(s.Template!.ApplicationsInWork!.NextRun))) //.ForMember(d => d.GenerationTime, o => o.MapFrom(s => EsppScheduleHelpers.GetGenerationTime(s.Template!.ApplicationsInWork!.NextRun)))
//.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextRun(s.Template!.ApplicationsInWork!.NextRun)))
//~~~~~~~~~
.ForMember(d => d.GenerationTime, o => o.MapFrom(s => EsppScheduleHelpers.GetGenerationTime(s.Template!.NextRun)))
.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextRun(s.Template!.NextRun)))
//.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetFirstStart(s.Template!.ApplicationsInWork!.ScheduleStartDate, s.Template!.ApplicationsInWork!.ScheduleGenerationTime))) //.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetFirstStart(s.Template!.ApplicationsInWork!.ScheduleStartDate, s.Template!.ApplicationsInWork!.ScheduleGenerationTime)))
//.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextScheduleStart(s.Template!.NextScheduleStart))) //.ForMember(d => d.NextStart, o => o.MapFrom(s => EsppScheduleHelpers.GetNextScheduleStart(s.Template!.NextScheduleStart)))
.ForMember(d => d.ScheduleType, o => o.MapFrom(s => .ForMember(d => d.ScheduleType, o => o.MapFrom(s =>

View File

@@ -38,8 +38,10 @@ namespace PARR.API.MappingProfiles.Resolvers
var response = new EsppScheduleResponse var response = new EsppScheduleResponse
{ {
NextRun = source.ApplicationsInWork!.NextRun, //NextRun = source.ApplicationsInWork!.NextRun,
LastRun = source.ApplicationsInWork.LastRun, //LastRun = source.ApplicationsInWork.LastRun,
NextRun = source.NextRun,
LastRun = source.LastRun,
Timezone = settingsFromDb.ScheduleTimezone, Timezone = settingsFromDb.ScheduleTimezone,
TypeSchedule = mapper.Map<EsppScheduleTypeScheduleResponse>(schedule.TypeSchedule), TypeSchedule = mapper.Map<EsppScheduleTypeScheduleResponse>(schedule.TypeSchedule),
Values = mapper.Map<List<EsppScheduleValResponse>>(schedule.Values).OrderBy(t => t.Order).ToList() Values = mapper.Map<List<EsppScheduleValResponse>>(schedule.Values).OrderBy(t => t.Order).ToList()

View File

@@ -5,6 +5,7 @@ namespace PARR.API.Settings
public class MqSettings public class MqSettings
{ {
public MqGenerateTemplates GenerateTemplates { get; set; } = new MqGenerateTemplates(); public MqGenerateTemplates GenerateTemplates { get; set; } = new MqGenerateTemplates();
public MqTemplateDistributor TemplateDistributor { get; set; } = new MqTemplateDistributor();
public MqStatistics Statistics { get; set; } = new MqStatistics(); public MqStatistics Statistics { get; set; } = new MqStatistics();
} }
@@ -16,6 +17,14 @@ namespace PARR.API.Settings
public string Password { get; set; } = string.Empty; public string Password { get; set; } = string.Empty;
} }
public class MqTemplateDistributor : IMqSettings
{
public string HostName { get; set; } = string.Empty;
public string QueueName { get; set; } = string.Empty;
public string User { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}
public class MqStatistics public class MqStatistics
{ {
public StatMqAuth StatMqAuth { get; set; } = new StatMqAuth(); public StatMqAuth StatMqAuth { get; set; } = new StatMqAuth();

View File

@@ -1,5 +1,6 @@
using FluentValidation; using FluentValidation;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using PARR.API.Contracts.V1.Requests; using PARR.API.Contracts.V1.Requests;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
@@ -11,18 +12,21 @@ namespace PARR.API.Validators
private readonly IWorkService workService; private readonly IWorkService workService;
private readonly IEsppSchTypeConfigService esppSchTypeConfigService; private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
private readonly IWorkGroupService workGroupService; private readonly IWorkGroupService workGroupService;
private readonly IEsppSchTypeValueService esppSchTypeValueService;
public ApplicationInWorkValidator( public ApplicationInWorkValidator(
IApplicationsInWorkService applicationsInWorkService, IApplicationsInWorkService applicationsInWorkService,
IWorkService workService, IWorkService workService,
IEsppSchTypeConfigService esppSchTypeConfigService, IEsppSchTypeConfigService esppSchTypeConfigService,
IWorkGroupService workGroupService IWorkGroupService workGroupService,
IEsppSchTypeValueService esppSchTypeValueService
) )
{ {
this.applicationsInWorkService = applicationsInWorkService; this.applicationsInWorkService = applicationsInWorkService;
this.workService = workService; this.workService = workService;
this.esppSchTypeConfigService = esppSchTypeConfigService; this.esppSchTypeConfigService = esppSchTypeConfigService;
this.workGroupService = workGroupService; this.workGroupService = workGroupService;
this.esppSchTypeValueService = esppSchTypeValueService;
RuleFor(t => t.TemplateDuration) RuleFor(t => t.TemplateDuration)
.NotNull().NotEmpty()//.WithMessage("Длительность данного задания на выполнение работ не может быть пустым") .NotNull().NotEmpty()//.WithMessage("Длительность данного задания на выполнение работ не может быть пустым")
@@ -96,8 +100,36 @@ namespace PARR.API.Validators
RuleFor(t => t.WorkGroups) RuleFor(t => t.WorkGroups)
.MustAsync(async (entity, value, c) => await IsWorkGroupsExistAsync(entity)) .MustAsync(async (entity, value, c) => await IsWorkGroupsExistAsync(entity))
.WithMessage("Указаные несуществующие Id рабочих групп"); .WithMessage("Указаные несуществующие Id рабочих групп");
//Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId
RuleFor(t => t.IsAutoDistributionEnabled)
.MustAsync(async (entity, value, c) => await IsAllowAutoDistributionEnabledAsync(entity, value))
.WithMessage("Нельзя включить автораспределение для этого типа расписания");
} }
private async Task<bool> IsAllowAutoDistributionEnabledAsync(ApplicationInWorkRequest entity, bool value)
{
//Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId
if (value == false)
return true;
//Распределение включено, смотрим, разрешено ли оно в расписании
//по идее, это расписание только с одним значением в EsppSchValues, но мы проверим у всех, но такого быть не может по хорошему
foreach (var item in entity.Schedule)
{
var schVal = await esppSchTypeValueService.GetAsync(item.TypeValueId);
if (schVal != null)
if (schVal.DistributionPeriodId == null)
return false;
}
return true;
}
private async Task<bool> IsWorkGroupsExistAsync(ApplicationInWorkRequest entity) private async Task<bool> IsWorkGroupsExistAsync(ApplicationInWorkRequest entity)
{ {
var result = await workGroupService.Get().Where(t => entity.WorkGroups.Contains(t.Id)).ToListAsync(); var result = await workGroupService.Get().Where(t => entity.WorkGroups.Contains(t.Id)).ToListAsync();

View File

@@ -0,0 +1,24 @@
using FluentValidation;
using PARR.API.Contracts.V1.Requests;
using PARR.DAL.Services.Interfaces;
namespace PARR.API.Validators
{
public class DistributeRequestValidator : AbstractValidator<DistributeRequest>
{
private readonly IApplicationsInWorkService applicationsInWorkService;
public DistributeRequestValidator(IApplicationsInWorkService applicationsInWorkService)
{
this.applicationsInWorkService = applicationsInWorkService;
RuleFor(t => t.ApplicationInWorkId).NotEmpty().MustAsync(async (entity, value, c) =>
{
var appInWork = await applicationsInWorkService.GetAsync(value);
return appInWork != null;
}).WithMessage("Недопустимое значение");
}
}
}

View File

@@ -24,6 +24,9 @@
"GenerateTemplates": { "GenerateTemplates": {
"HostName": "10.99.253.216" "HostName": "10.99.253.216"
}, },
"TemplateDistributor": {
"HostName": "10.99.253.216"
},
"Statistics": { "Statistics": {
"StatMqAuth": { "StatMqAuth": {
"HostName": "10.99.253.216" "HostName": "10.99.253.216"

View File

@@ -45,6 +45,12 @@
"User": "generate_templates_api", "User": "generate_templates_api",
"Password": "DHhjgdsf*&%95" "Password": "DHhjgdsf*&%95"
}, },
"TemplateDistributor": {
"HostName": "parr-rabbitmq",
"QueueName": "parr-template-distributor",
"User": "espp_template_distributor_writer",
"Password": "KGgsdfu%%44qqwew"
},
"Statistics": { "Statistics": {
"StatMqAuth": { "StatMqAuth": {
"HostName": "parr-rabbitmq", "HostName": "parr-rabbitmq",

View File

@@ -69,15 +69,15 @@ namespace PARR.DAL.Models
public required string Solution { get; set; } public required string Solution { get; set; }
/// <summary> ///// <summary>
/// Время последнего запуска скрипта/генерации наряда ///// Время последнего запуска скрипта/генерации наряда
/// </summary> ///// </summary>
public DateTimeOffset? LastRun { get; set; } //public DateTimeOffset? LastRun { get; set; }
/// <summary> ///// <summary>
/// Время следующего запуска скрипта/генерации наряда ///// Время следующего запуска скрипта/генерации наряда
/// </summary> ///// </summary>
public DateTimeOffset NextRun { get; set; } //public DateTimeOffset NextRun { get; set; }
/// <summary> /// <summary>
/// Включить автораспределение /// Включить автораспределение
@@ -89,7 +89,6 @@ namespace PARR.DAL.Models
/// </summary> /// </summary>
public DateTimeOffset ReferenceDate { get; set; } public DateTimeOffset ReferenceDate { get; set; }
/// <summary> /// <summary>
/// Выполняет агент /// Выполняет агент
/// </summary> /// </summary>

View File

@@ -82,6 +82,7 @@ namespace PARR.DAL
services.AddTransient<IEsppSchTypeScheduleService, EsppSchTypeScheduleService>(); services.AddTransient<IEsppSchTypeScheduleService, EsppSchTypeScheduleService>();
services.AddTransient<IWeekendDayService, WeekendDayService>(); services.AddTransient<IWeekendDayService, WeekendDayService>();
services.AddTransient<IDistributionPeriodService, DistributionPeriodService>(); services.AddTransient<IDistributionPeriodService, DistributionPeriodService>();
services.AddTransient<IEsppSchTypeValueService, EsppSchTypeValueService>();
// TransformServices // TransformServices
services.AddTransient<IEsppScheduleTransformService, EsppScheduleTransformService>(); services.AddTransient<IEsppScheduleTransformService, EsppScheduleTransformService>();

View File

@@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.DAL.Context;
using PARR.DAL.Models;
using PARR.DAL.Services.Abstracts;
using PARR.DAL.Services.Interfaces;
namespace PARR.DAL.Services.Implementations
{
internal class EsppSchTypeValueService : BaseService<EsppSchTypeValue>, IEsppSchTypeValueService
{
private readonly DataContext dataContext;
protected override DbSet<EsppSchTypeValue> EntitySet => dataContext.EsppSchTypeValues;
protected override DataContext EntitiContext => dataContext;
public EsppSchTypeValueService(DataContext dataContext, ILogger<EsppSchTypeValueService> logger): base(logger)
{
this.dataContext = dataContext;
}
}
}

View File

@@ -0,0 +1,9 @@
using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces.Base;
namespace PARR.DAL.Services.Interfaces
{
public interface IEsppSchTypeValueService : IBaseService<EsppSchTypeValue>
{
}
}

View File

@@ -53,7 +53,8 @@ namespace PARR.EsppOrderLoader.Services
StatusCode = (int)orderStatusService.GetOrderStatusByName(esppOrder.Status), StatusCode = (int)orderStatusService.GetOrderStatusByName(esppOrder.Status),
GenerateDate = template == null ? GenerateDate = template == null ?
null null
: CalcGenerationDate(template.ApplicationsInWork!.NextRun, template.ApplicationsInWork!.LastRun), //: CalcGenerationDate(template.ApplicationsInWork!.NextRun, template.ApplicationsInWork!.LastRun),
: CalcGenerationDate(template.NextRun, template.LastRun),
//CalcGenerationDate(esppOrder.ExpirationDateUTC, template.ApplicationsInWork!.TemplateDurationTimeSpan), //CalcGenerationDate(esppOrder.ExpirationDateUTC, template.ApplicationsInWork!.TemplateDurationTimeSpan),
ExpirationDate = esppOrder.ExpirationDateUTC ExpirationDate = esppOrder.ExpirationDateUTC
}; };

View File

@@ -88,7 +88,8 @@ namespace PARR.EsppScheduleSync
WorkGroup = template.Host!.WorkGroup!.Name, WorkGroup = template.Host!.WorkGroup!.Name,
//Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать //Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "", TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "",
Scheduled = EsppScheduleHelpers.GetNextRun(template.ApplicationsInWork!.NextRun), //Scheduled = EsppScheduleHelpers.GetNextRun(template.ApplicationsInWork!.NextRun),
Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
Timezone = settingsFromDb.ScheduleTimezone, Timezone = settingsFromDb.ScheduleTimezone,
//Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать //Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать
TerminationType = settingsFromDb.ScheduleRepeatRange == "Отсутствует дата завершения" ? "forever" : "", TerminationType = settingsFromDb.ScheduleRepeatRange == "Отсутствует дата завершения" ? "forever" : "",

View File

@@ -9,6 +9,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PARR.BLL\PARR.BLL.csproj" /> <ProjectReference Include="..\PARR.BLL\PARR.BLL.csproj" />
<ProjectReference Include="..\PARR.DAL\PARR.DAL.csproj" /> <ProjectReference Include="..\PARR.DAL\PARR.DAL.csproj" />
<ProjectReference Include="..\PARR.TemplateDistributor\PARR.TemplateDistributor.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -7,6 +7,7 @@ using PARR.DAL.Contracts;
using PARR.DAL.Extensions; using PARR.DAL.Extensions;
using PARR.DAL.Models; using PARR.DAL.Models;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.TemplateDistributor;
using System.Text.Json; using System.Text.Json;
namespace PARR.GeneratorTemplates.Services namespace PARR.GeneratorTemplates.Services
@@ -19,6 +20,7 @@ namespace PARR.GeneratorTemplates.Services
private readonly SettingsFromDb settingsFromDb; private readonly SettingsFromDb settingsFromDb;
private readonly IRobotConfigurationService robotConfigurationService; private readonly IRobotConfigurationService robotConfigurationService;
private readonly IApplicationsInWorkService applicationsInWorkService; private readonly IApplicationsInWorkService applicationsInWorkService;
private readonly ITemplateDistributor templateDistributor;
public TemplateManager( public TemplateManager(
ITemplateService templateService, ITemplateService templateService,
@@ -26,7 +28,8 @@ namespace PARR.GeneratorTemplates.Services
ILogger<TemplateManager> logger, ILogger<TemplateManager> logger,
SettingsFromDb settingsFromDb, SettingsFromDb settingsFromDb,
IRobotConfigurationService robotConfigurationService, IRobotConfigurationService robotConfigurationService,
IApplicationsInWorkService applicationsInWorkService IApplicationsInWorkService applicationsInWorkService,
ITemplateDistributor templateDistributor
) )
{ {
this.templateService = templateService; this.templateService = templateService;
@@ -35,6 +38,7 @@ namespace PARR.GeneratorTemplates.Services
this.settingsFromDb = settingsFromDb; this.settingsFromDb = settingsFromDb;
this.robotConfigurationService = robotConfigurationService; this.robotConfigurationService = robotConfigurationService;
this.applicationsInWorkService = applicationsInWorkService; this.applicationsInWorkService = applicationsInWorkService;
this.templateDistributor = templateDistributor;
} }
public async Task CreateTemplates(GeneratorTemplateMq query) public async Task CreateTemplates(GeneratorTemplateMq query)
@@ -95,7 +99,85 @@ namespace PARR.GeneratorTemplates.Services
} }
//Создаем шаблоны // хосты группируем по РГ, чтоб потом распределить/рассчитать NextRun
var groupingHostByWg = hosts.GroupBy(t => t.WorkGroupId);
foreach (var group in groupingHostByWg)
{
var groupingHosts = group.ToList();
var templates = CreateQueryTemplates(groupingHosts, query);
//заполняем NextRun
templates = await templateDistributor.DistributeTemplateAsync(templates, appInWorkWg.Id, (Guid)group.Key!);
// сохраняем
foreach (var template in templates)
{
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}");
}
}
}
#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.Shortcodes.EK, host.Ek)),
// //Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
// Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(
// host.ResponseArea!.Name,
// settingsFromDb.TemplatePrefixName,
// host.Ek,
// appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.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
}
private List<Template> CreateQueryTemplates(List<Host> hosts, GeneratorTemplateMq query)
{
var templates = new List<Template>();
foreach (var host in hosts) foreach (var host in hosts)
{ {
var appInWork = host.ApplicationsInHosts.FirstOrDefault(t => t.ApplicationId == query.ApplicationId)?.Application?.ApplicationsInWorks.FirstOrDefault(a => a.WorkId == query.WorkId); var appInWork = host.ApplicationsInHosts.FirstOrDefault(t => t.ApplicationId == query.ApplicationId)?.Application?.ApplicationsInWorks.FirstOrDefault(a => a.WorkId == query.WorkId);
@@ -104,43 +186,40 @@ namespace PARR.GeneratorTemplates.Services
{ {
// такого не может быть, так как выполнился запрос при получении списка хостов, но мало ли // такого не может быть, так как выполнился запрос при получении списка хостов, но мало ли
logger.LogError($"Ошибка при создании шаблона. В таблице ApplicationsInWorks не найден Id согласно запроса WorkId: {query.WorkId}, ApplicationId: {query.ApplicationId}"); logger.LogError($"Ошибка при создании шаблона. В таблице ApplicationsInWorks не найден Id согласно запроса WorkId: {query.WorkId}, ApplicationId: {query.ApplicationId}");
return; //return;
return templates;
} }
var template = new Template var template = new Template
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
//TODO:!!!
//Name = TemplateHelpers.GenerateTemplateName("ЗО" ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name), //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.Shortcodes.EK, host.Ek)), //Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.EK, host.Ek)),
//Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет //Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
Name = TemplateHelpers.GenerateTemplateNameWithResponseArea( Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(
host.ResponseArea!.Name, host.ResponseArea!.Name,
settingsFromDb.TemplatePrefixName, settingsFromDb.TemplatePrefixName,
host.Ek, host.Ek,
appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.EK, host.Ek) appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.EK, host.Ek)
), ),
//IsActiveTemplate = true,
//IsActiveSchedule = true,
IsActiveTemplate = query.IsActiveTemplate ?? false, IsActiveTemplate = query.IsActiveTemplate ?? false,
IsActiveSchedule = query.IsActiveSchedule ?? false, IsActiveSchedule = query.IsActiveSchedule ?? false,
ApplicationInWorkId = appInWork.Id, ApplicationInWorkId = appInWork.Id,
HostId = host.Id HostId = host.Id,
// NextRun не задаем значение, его рассчитаем позже
//NextRun = ???,
LastRun = null
}; };
if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync()) templates.Add(template);
{
logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}");
}
else
{
logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " +
$"HostId: {template.HostId}");
}
} }
return templates;
} }
public async Task DeactivateTemplates(GeneratorTemplateMq query) public async Task DeactivateTemplates(GeneratorTemplateMq query)
{ {
//TODO: !!! тут не учитываются поля query.IsActiveTemplate, query.IsActiveSchedule, просто все деактивируется. !!! //TODO: !!! тут не учитываются поля query.IsActiveTemplate, query.IsActiveSchedule, просто все деактивируется. !!!

View File

@@ -8,6 +8,7 @@ WORKDIR /src
COPY ["NuGet.config", "."] COPY ["NuGet.config", "."]
COPY ["PARR.GeneratorTemplatesWorker/PARR.GeneratorTemplatesWorker.csproj", "PARR.GeneratorTemplatesWorker/"] COPY ["PARR.GeneratorTemplatesWorker/PARR.GeneratorTemplatesWorker.csproj", "PARR.GeneratorTemplatesWorker/"]
COPY ["PARR.GeneratorTemplates/PARR.GeneratorTemplates.csproj", "PARR.GeneratorTemplates/"] COPY ["PARR.GeneratorTemplates/PARR.GeneratorTemplates.csproj", "PARR.GeneratorTemplates/"]
COPY ["PARR.TemplateDistributor/PARR.TemplateDistributor.csproj", "PARR.TemplateDistributor/"]
COPY ["PARR.BLL/PARR.BLL.csproj", "PARR.BLL/"] COPY ["PARR.BLL/PARR.BLL.csproj", "PARR.BLL/"]
COPY ["PARR.DAL/PARR.DAL.csproj", "PARR.DAL/"] COPY ["PARR.DAL/PARR.DAL.csproj", "PARR.DAL/"]
COPY ["PARR.Constants/PARR.Constants.csproj", "PARR.Constants/"] COPY ["PARR.Constants/PARR.Constants.csproj", "PARR.Constants/"]

View File

@@ -36,13 +36,14 @@ namespace PARR.NextRun
{ {
using (var scope = serviceProvider.CreateScope()) using (var scope = serviceProvider.CreateScope())
{ {
var appInWorkService = scope.ServiceProvider.GetService<IApplicationsInWorkService>(); //var appInWorkService = scope.ServiceProvider.GetService<IApplicationsInWorkService>();
var esppSchService = scope.ServiceProvider.GetService<IEsppScheduleTransformService>(); var esppSchService = scope.ServiceProvider.GetService<IEsppScheduleTransformService>();
var templateService = scope.ServiceProvider.GetService<ITemplateService>();
if (appInWorkService == null || esppSchService == null) if (templateService == null || esppSchService == null)
throw new Exception("Не смог получить серивс IApplicationsInWorkService или IEsppScheduleTransformService"); throw new Exception("Не смог получить серивс ITemplateService или IEsppScheduleTransformService");
await HandlerAsync(appInWorkService, esppSchService); await HandlerAsync(templateService, esppSchService);
} }
}, workerSettings.RepeatEvery); }, workerSettings.RepeatEvery);
} }
@@ -52,30 +53,30 @@ namespace PARR.NextRun
/// Рассчет следующей даты срабатываения /// Рассчет следующей даты срабатываения
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private async Task HandlerAsync(IApplicationsInWorkService applicationsInWorkService, IEsppScheduleTransformService esppScheduleTransformService) private async Task HandlerAsync(ITemplateService templateService, IEsppScheduleTransformService esppScheduleTransformService)
{ {
var objs = await applicationsInWorkService.Get().Where(t => t.NextRun < DateTimeOffset.UtcNow).ToListAsync(); var templates = await templateService.Get().Where(t => t.NextRun < DateTimeOffset.UtcNow).ToListAsync();
logger.LogDebug($"Объектов для обновления: {objs.Count()} шт."); logger.LogDebug($"Шаблонов для обновления: {templates.Count()} шт.");
int errorsCount = 0; int errorsCount = 0;
foreach (var obj in objs) foreach (var template in templates)
{ {
var nextRun = await esppScheduleTransformService.GetNextDateAsync(obj.Id, obj.NextRun); var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.ApplicationInWorkId, template.NextRun);
obj.LastRun = obj.NextRun; template.LastRun = template.NextRun;
obj.NextRun = nextRun; template.NextRun = nextRun;
if (await applicationsInWorkService.CommitAsync()) if (await templateService.CommitAsync())
logger.LogDebug($"Обновлено значение полей NextRun: {obj.NextRun}, LastRun: {obj.LastRun} для строки {obj.Id}"); logger.LogDebug($"Обновлены значения полей NextRun: {template.NextRun}, LastRun: {template.LastRun} для шаблона {template.Name}, {template.Id}");
else else
{ {
logger.LogError($"Ошибка при обновлении значения полей NextRun {obj.NextRun}, LastRun: {obj.LastRun} для строки {obj.Id}"); logger.LogError($"Ошибка при обновлении значений полей NextRun: {template.NextRun}, LastRun: {template.LastRun} для шаблона {template.Name}, {template.Id}");
errorsCount++; errorsCount++;
} }
} }
logger.LogInformation($"Завершено обновление полей NextRun. Полей в задании: {objs.Count()}, обновлено: {objs.Count() - errorsCount}, ошибок: {errorsCount}"); logger.LogInformation($"Завершено обновление полей NextRun. Полей в задании: {templates.Count()}, обновлено: {templates.Count() - errorsCount}, ошибок: {errorsCount}");
} }
} }
} }

View File

@@ -86,9 +86,7 @@ namespace PARR.TemplateDistributor
} }
public async Task<List<Template>> DistributeTemplateAsync(List<Template> templates, Guid applicationInWorkId, Guid workGroupid) public async Task<List<Template>> DistributeTemplateAsync(List<Template> templates, Guid applicationInWorkId, Guid workGroupid)
//public async Task<List<Template>> DistributeTemplateAsync(List<Template> templates, Guid applicationInWorkId)
{ {
//TODO: ЗАГУЛШКА переделать! //TODO: ЗАГУЛШКА переделать!