2024-02-05 16:05:02 +10:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Logging ;
using PARR.BLL.Services.Interfaces ;
2024-10-08 16:37:58 +10:00
using PARR.Common.Domain ;
2025-12-01 15:27:18 +10:00
using PARR.Constants ;
2026-01-22 11:46:05 +10:00
using PARR.DAL.NextRunServices ;
2024-02-05 16:05:02 +10:00
using PARR.DAL.Services.Interfaces ;
2025-11-25 16:49:28 +10:00
using PARR.DAL.Services.Interfaces.Job ;
2024-02-05 16:05:02 +10:00
using PARR.NextRun.Settings ;
namespace PARR.NextRun
{
internal class NextRunManager : INextRunManager
{
private readonly WorkerSettings workerSettings ;
private readonly ILogger < NextRunManager > logger ;
private readonly IIntervalService intervalService ;
private readonly IServiceProvider serviceProvider ;
public NextRunManager (
WorkerSettings workerSettings ,
ILogger < NextRunManager > logger ,
IIntervalService intervalService ,
IServiceProvider serviceProvider
)
{
this . workerSettings = workerSettings ;
this . logger = logger ;
this . intervalService = intervalService ;
this . serviceProvider = serviceProvider ;
}
public async Task StartAsync ( )
{
logger . LogInformation ( "Запуск сервиса рассчета времени следующего создания наряда (nextRun)" ) ;
await intervalService . IntervalInitAsync ( async ( ) = >
{
using ( var scope = serviceProvider . CreateScope ( ) )
{
2024-07-03 15:19:09 +10:00
//var appInWorkService = scope.ServiceProvider.GetService<IApplicationsInWorkService>();
2026-01-22 11:46:05 +10:00
//var esppSchService = scope.ServiceProvider.GetService<IEsppScheduleTransformService>();
2024-07-03 15:19:09 +10:00
var templateService = scope . ServiceProvider . GetService < ITemplateService > ( ) ;
2025-11-25 16:49:28 +10:00
var jobGroupService = scope . ServiceProvider . GetService < IJobGroupService > ( ) ;
2026-01-22 11:46:05 +10:00
var nextRunService = scope . ServiceProvider . GetService < INextRunService > ( ) ;
2024-02-05 16:05:02 +10:00
2026-01-22 11:46:05 +10:00
if ( templateService = = null | | nextRunService = = null | | jobGroupService = = null )
throw new Exception ( $"Н е смог получить серивс {nameof(ITemplateService)} или {nameof(INextRunService)} или {nameof(IJobGroupService)}" ) ;
2024-02-05 16:05:02 +10:00
2026-01-22 11:46:05 +10:00
await HandlerAsync ( templateService , nextRunService , jobGroupService ) ;
2024-02-05 16:05:02 +10:00
}
} , workerSettings . RepeatEvery ) ;
}
/// <summary>
/// Рассчет следующей даты срабатываения
/// </summary>
/// <returns></returns>
2026-01-22 11:46:05 +10:00
private async Task HandlerAsync ( ITemplateService templateService , INextRunService nextRunService , IJobGroupService jobGroupService )
2024-02-05 16:05:02 +10:00
{
2026-01-23 09:28:14 +10:00
logger . LogInformation ( "Начинаю обновлять NextRun по расписанию" ) ;
2024-02-05 16:05:02 +10:00
2026-02-05 15:41:36 +10:00
//// обновляем для групп у которых не включено автораспределение
//await UpdateNextRunWithEsppScheduleAsync(templateService, nextRunService, jobGroupService);
2026-01-23 09:28:14 +10:00
2026-02-05 15:41:36 +10:00
//// для групп у которых включено автораспределение
//await UpdateNextRunWithAutodistributeScheduleAsync(templateService, nextRunService, jobGroupService);
await UpdateNextRunAsync ( templateService , nextRunService , jobGroupService ) ;
2026-01-23 09:28:14 +10:00
logger . LogInformation ( $"Завершено обновление полей NextRun." ) ;
}
2026-02-05 15:41:36 +10:00
private async Task UpdateNextRunAsync ( ITemplateService templateService , INextRunService nextRunService , IJobGroupService jobGroupService )
{
// выбираем все шаблоны с просроченным nextRun в статусе Used
var templatesForUpdate = await templateService . Get ( )
. Where ( t = >
t . StatusTypeId = = TemplateStatusTypeEnum . Used
& & t . NextRun < DateTimeOffset . UtcNow
) . ToListAsync ( ) ;
logger . LogInformation ( "Найдено шаблонов в статусе Used с просроченным NextRun {count} шт." , templatesForUpdate . Count ) ;
if ( ! templatesForUpdate . Any ( ) )
return ;
foreach ( var template in templatesForUpdate )
{
var newNextRun = await nextRunService . GetNextRunForTemplateAsync ( template . Id , false ) ;
template . LastRun = template . NextRun ;
template . NextRun = newNextRun ;
}
if ( await templateService . CommitAsync ( new HistoryInitiator { InitiatorComment = "Обновлён NextRun" , InitiatorParrComponentId = ParrComponentsEnum . NextRun } ) )
{
logger . LogInformation ( "Обновлены значения полей NextRun для шаблонов в статусе Used, {count} шт." , templatesForUpdate . Count ) ;
}
else
{
logger . LogError ( "Ошибка при обновлении значений полей NextRun, для шаблонов в статусе Used, {count} шт." , templatesForUpdate . Count ) ;
}
}
#region old
2026-01-23 09:28:14 +10:00
/// <summary>
/// Обновить nextRun для В С Е Х шаблонов, для групп у которых расписание ЕСПП (выключено автораспределение)
/// </summary>
/// <returns></returns>
private async Task UpdateNextRunWithEsppScheduleAsync ( ITemplateService templateService , INextRunService nextRunService , IJobGroupService jobGroupService )
{
2025-11-25 16:49:28 +10:00
// выбираем шаблоны которые не учавствуют в автораспределении
2026-01-23 09:28:14 +10:00
// и у которых Used
// обновляем для всех шаблонов, у которых nextRun!=рассчитанному
2024-02-05 16:05:02 +10:00
2026-02-05 15:41:36 +10:00
var templatesForUpdate = await templateService . Get ( )
. Where ( t = >
t . StatusTypeId = = TemplateStatusTypeEnum . Used
& & t . Job ! . Group ! . IsAutoDistributionEnabled = = false
& & t . NextRun < DateTimeOffset . UtcNow
) . ToListAsync ( ) ;
2024-02-05 16:05:02 +10:00
2025-11-25 16:49:28 +10:00
2026-02-05 15:41:36 +10:00
logger . LogInformation ( "Найдено шаблонов с выключенным автораспределением, с просроченным NextRun {count} шт." , templatesForUpdate . Count ) ;
2025-11-25 16:49:28 +10:00
2026-02-05 15:41:36 +10:00
if ( ! templatesForUpdate . Any ( ) )
return ;
foreach ( var template in templatesForUpdate )
2024-02-05 16:05:02 +10:00
{
2026-02-05 15:41:36 +10:00
var newNextRun = await nextRunService . GetNextRunForTemplateAsync ( template . Id , false ) ;
2025-11-25 16:49:28 +10:00
2026-02-05 15:41:36 +10:00
template . LastRun = template . NextRun ;
template . NextRun = newNextRun ;
}
2025-11-25 16:49:28 +10:00
2026-02-05 15:41:36 +10:00
if ( await templateService . CommitAsync ( new HistoryInitiator { InitiatorComment = "Обновлён NextRun" , InitiatorParrComponentId = ParrComponentsEnum . NextRun } ) )
{
logger . LogInformation ( "Обновлены значения ПРОСРОЧЕННЫХ полей NextRun для шаблонов с ВЫКЛЮЧЕННЫМ автораспределением, {count} шт." , templatesForUpdate . Count ) ;
}
else
{
logger . LogError ( "Ошибка при обновлении ПРОСРОЧЕННЫХ значений полей NextRun, для шаблонов {count} шт., с ВЫКЛЮЧЕННЫМ автораспределением" , templatesForUpdate . Count ) ;
}
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
2026-02-05 15:41:36 +10:00
//// выбираем шаблоны которые не учавствуют в автораспределении
//// и у которых Used
//// затем группируем по GroupId, так как nextRun и расписание настраивается для группы, то для всех дочерних шаблонов, nextRun будет одинаковым
//// обновляем для всех шаблонов, у которых nextRun!=рассчитанному
2024-02-05 16:05:02 +10:00
2025-11-25 16:49:28 +10:00
2026-02-05 15:41:36 +10:00
//var groups = await jobGroupService.Get()
// .Where(t => t.IsAutoDistributionEnabled == false)
// .Select(t => new { t.Id, t.ReferenceDate })
// .ToListAsync();
//logger.LogInformation("Найдено {GroupCount} групп с выключенным автораспределением для обработки.", groups.Count);
//foreach (var group in groups)
//{
// //получаем по каждой группе следующий nextRun и сравниваем с существующим, если не равны, то обновляем
// //var nextRun = await esppScheduleTransformService.GetNextDateAsync(group.Id, group.ReferenceDate);
// var nextRun = await nextRunService.GetNextRunForJobGroupWithEsppSchedulleAsync(group.Id);
// // Загружаем только шаблоны текущей группы где nextRun в БД не равен расчетному
// var templatesToUpdate = await templateService.Get()
// .Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Used && t.Job!.GroupId == group.Id && t.NextRun != nextRun)
// .ToListAsync();
// logger.LogInformation("Для группы {groupId}, шаблонов для обновления где nextRun!=рассчетному {newNextRun} найдено {count} шт.", group.Id, nextRun, templatesToUpdate.Count);
// if (!templatesToUpdate.Any())
// continue;
// // Обновляем
// foreach (var template in templatesToUpdate)
// {
// template.LastRun = template.NextRun;
// template.NextRun = nextRun;
// }
// // Коммитим изменения для этой группы
// if (await templateService.CommitAsync(new HistoryInitiator { InitiatorComment = "Обновлён NextRun", InitiatorParrComponentId = ParrComponentsEnum.NextRun }))
// logger.LogInformation($"Обновлены значения полей NextRun для шаблонов группы: {group.Id} с выключенным автораспределением, " +
// $"refDate: {group.ReferenceDate}. Обновлен nextRun: {nextRun} для шаблонов {templatesToUpdate.Count} шт.");
// else
// {
// logger.LogError($"Ошибка при обновлении значений полей NextRun: {nextRun}, для шаблонов {templatesToUpdate.Count} шт., группы {group.Id} с выключенным автораспределением, refDate: {group.ReferenceDate} ");
// }
//}
2026-01-23 09:28:14 +10:00
}
2024-02-05 16:05:02 +10:00
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
/// <summary>
/// Обновить ПРОСРОЧЕННЫЕ NextRun для групп у которых включено автораспределение
/// </summary>
/// <param name="templateService"></param>
/// <param name="nextRunService"></param>
/// <param name="jobGroupService"></param>
/// <returns></returns>
private async Task UpdateNextRunWithAutodistributeScheduleAsync ( ITemplateService templateService , INextRunService nextRunService , IJobGroupService jobGroupService )
{
// получаем список всех шаблонов с включенным автораспределением у которых ПРОСРОЧЕН nextRun и они Used
// обновляем у них NextRun
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
var templatesForUpdate = await templateService . Get ( )
. Where ( t = > t . StatusTypeId = = TemplateStatusTypeEnum . Used & & t . Job . Group . IsAutoDistributionEnabled = = true & & t . NextRun < DateTimeOffset . UtcNow )
. ToListAsync ( ) ;
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
logger . LogInformation ( "Найдено шаблонов с автораспределением, с просроченным NextRun {count} шт." , templatesForUpdate . Count ) ;
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
if ( ! templatesForUpdate . Any ( ) )
return ;
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
foreach ( var template in templatesForUpdate )
{
var newNextRun = await nextRunService . GetNextRunForTemplateAsync ( template . Id , false ) ;
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
template . LastRun = template . NextRun ;
template . NextRun = newNextRun ;
}
2025-11-25 16:49:28 +10:00
2026-01-23 09:28:14 +10:00
if ( await templateService . CommitAsync ( new HistoryInitiator { InitiatorComment = "Обновлён NextRun" , InitiatorParrComponentId = ParrComponentsEnum . NextRun } ) )
{
logger . LogInformation ( "Обновлены значения ПРОСРОЧЕННЫХ полей NextRun для шаблонов с ВКЛЮЧЕННЫМ автораспределением, {count} шт." , templatesForUpdate . Count ) ;
}
else
{
logger . LogError ( "Ошибка при обновлении ПРОСРОЧЕННЫХ значений полей NextRun, для шаблонов {count} шт., с ВКЛЮЧЕННЫМ автораспределением" , templatesForUpdate . Count ) ;
}
2024-02-05 16:05:02 +10:00
}
2026-02-05 15:41:36 +10:00
#endregion
2024-02-05 16:05:02 +10:00
}
}