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-01-23 09:28:14 +10:00
// обновляем для групп у которых не включено автораспределение
await UpdateNextRunWithEsppScheduleAsync ( templateService , nextRunService , jobGroupService ) ;
// для групп у которых включено автораспределение
await UpdateNextRunWithAutodistributeScheduleAsync ( templateService , nextRunService , jobGroupService ) ;
logger . LogInformation ( $"Завершено обновление полей NextRun." ) ;
}
/// <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
2025-11-25 16:49:28 +10:00
// затем группируем по GroupId, так как nextRun и расписание настраивается для группы, то для всех дочерних шаблонов, nextRun будет одинаковым
2026-01-23 09:28:14 +10:00
// обновляем для всех шаблонов, у которых nextRun!=рассчитанному
2024-02-05 16:05:02 +10:00
2025-11-25 16:49:28 +10:00
var groups = await jobGroupService . Get ( )
. Where ( t = > t . IsAutoDistributionEnabled = = false )
. Select ( t = > new { t . Id , t . ReferenceDate } )
. ToListAsync ( ) ;
2026-01-23 09:28:14 +10:00
logger . LogInformation ( "Найдено {GroupCount} групп с выключенным автораспределением для обработки." , groups . Count ) ;
2025-11-25 16:49:28 +10:00
foreach ( var group in groups )
2024-02-05 16:05:02 +10:00
{
2025-11-25 16:49:28 +10:00
//получаем по каждой группе следующий nextRun и сравниваем с существующим, если не равны, то обновляем
2026-01-22 11:46:05 +10:00
//var nextRun = await esppScheduleTransformService.GetNextDateAsync(group.Id, group.ReferenceDate);
2026-01-23 09:28:14 +10:00
var nextRun = await nextRunService . GetNextRunForJobGroupWithEsppSchedulleAsync ( group . Id ) ;
2025-11-25 16:49:28 +10:00
// Загружаем только шаблоны текущей группы где nextRun в БД не равен расчетному
var templatesToUpdate = await templateService . Get ( )
2025-12-01 15:27:18 +10:00
. Where ( t = > t . StatusTypeId = = TemplateStatusTypeEnum . Used & & t . Job ! . GroupId = = group . Id & & t . NextRun ! = nextRun )
2025-11-25 16:49:28 +10:00
. ToListAsync ( ) ;
2026-01-23 09:28:14 +10:00
logger . LogInformation ( "Для группы {groupId}, шаблонов для обновления где nextRun!=рассчетному {newNextRun} найдено {count} шт." , group . Id , nextRun , templatesToUpdate . Count ) ;
2025-11-25 16:49:28 +10:00
if ( ! templatesToUpdate . Any ( ) )
continue ;
2024-02-05 16:05:02 +10:00
2025-11-25 16:49:28 +10:00
// Обновляем
foreach ( var template in templatesToUpdate )
{
template . LastRun = template . NextRun ;
template . NextRun = nextRun ;
}
// Коммитим изменения для этой группы
2026-01-23 09:28:14 +10:00
if ( await templateService . CommitAsync ( new HistoryInitiator { InitiatorComment = "Обновлён NextRun" , InitiatorParrComponentId = ParrComponentsEnum . NextRun } ) )
logger . LogInformation ( $"Обновлены значения полей NextRun для шаблонов группы: {group.Id} с выключенным автораспределением, " +
2025-11-25 16:49:28 +10:00
$"refDate: {group.ReferenceDate}. Обновлен nextRun: {nextRun} для шаблонов {templatesToUpdate.Count} шт." ) ;
2024-02-05 16:05:02 +10:00
else
{
2026-01-23 09:28:14 +10:00
logger . LogError ( $"Ошибка при обновлении значений полей NextRun: {nextRun}, для шаблонов {templatesToUpdate.Count} шт., группы {group.Id} с выключенным автораспределением, refDate: {group.ReferenceDate} " ) ;
2024-02-05 16:05:02 +10:00
}
}
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
}
}
}