refactor(templateDistributor): добавлены комментарии
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -33,6 +33,9 @@ bld/
|
|||||||
[Ll]og/
|
[Ll]og/
|
||||||
[Ll]ogs/
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ namespace PARR.TemplateDistributor
|
|||||||
private readonly ILogger<TemplateDistributor> logger;
|
private readonly ILogger<TemplateDistributor> logger;
|
||||||
private readonly ITemplateService templateService;
|
private readonly ITemplateService templateService;
|
||||||
private readonly IApplicationsInWorkService applicationsInWorkService;
|
private readonly IApplicationsInWorkService applicationsInWorkService;
|
||||||
private readonly IEsppSchTypeScheduleService esppSchTypeScheduleService;
|
|
||||||
private readonly ICalendarService calendarService;
|
private readonly ICalendarService calendarService;
|
||||||
private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
private readonly IEsppScheduleTransformService esppScheduleTransformService;
|
||||||
private readonly IWeekendDayService weekendDayService;
|
private readonly IWeekendDayService weekendDayService;
|
||||||
@@ -22,7 +21,6 @@ namespace PARR.TemplateDistributor
|
|||||||
ILogger<TemplateDistributor> logger,
|
ILogger<TemplateDistributor> logger,
|
||||||
ITemplateService templateService,
|
ITemplateService templateService,
|
||||||
IApplicationsInWorkService applicationsInWorkService,
|
IApplicationsInWorkService applicationsInWorkService,
|
||||||
IEsppSchTypeScheduleService esppSchTypeScheduleService,
|
|
||||||
ICalendarService calendarService,
|
ICalendarService calendarService,
|
||||||
IEsppScheduleTransformService esppScheduleTransformService,
|
IEsppScheduleTransformService esppScheduleTransformService,
|
||||||
IWeekendDayService weekendDayService
|
IWeekendDayService weekendDayService
|
||||||
@@ -31,7 +29,6 @@ namespace PARR.TemplateDistributor
|
|||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.applicationsInWorkService = applicationsInWorkService;
|
this.applicationsInWorkService = applicationsInWorkService;
|
||||||
this.esppSchTypeScheduleService = esppSchTypeScheduleService;
|
|
||||||
this.calendarService = calendarService;
|
this.calendarService = calendarService;
|
||||||
this.esppScheduleTransformService = esppScheduleTransformService;
|
this.esppScheduleTransformService = esppScheduleTransformService;
|
||||||
this.weekendDayService = weekendDayService;
|
this.weekendDayService = weekendDayService;
|
||||||
@@ -40,57 +37,45 @@ namespace PARR.TemplateDistributor
|
|||||||
|
|
||||||
public async Task UpdateScheduleAsync(Guid applicationInWorkId)
|
public async Task UpdateScheduleAsync(Guid applicationInWorkId)
|
||||||
{
|
{
|
||||||
// все шаблоны по applicationInWorkId
|
|
||||||
// группирует по РР
|
|
||||||
// -> DistributeTemplateForPeriodAsync
|
|
||||||
// сохранить в БД
|
|
||||||
//applicationInWorkId = Guid.Parse("bdfefd77-bce3-4f62-a484-5042c06f4467");
|
|
||||||
|
|
||||||
var appInWork = await applicationsInWorkService.GetAsync(applicationInWorkId);
|
var appInWork = await applicationsInWorkService.GetAsync(applicationInWorkId);
|
||||||
// .Include(aiw => aiw.EsppSchValues)
|
|
||||||
// .ThenInclude(esv => esv.EsppSchTypeValue)
|
|
||||||
// .ThenInclude(etv => etv!.DistributionPeriod)
|
|
||||||
// .FirstOrDefaultAsync(t => t.Id == applicationInWorkId);
|
|
||||||
|
|
||||||
var templates = await templateService.Get()
|
var templates = await templateService.Get()
|
||||||
.Include(t => t.Host)
|
.Include(t => t.Host)
|
||||||
.ThenInclude(h => h.WorkGroup)
|
.ThenInclude(h => h.WorkGroup)
|
||||||
.Where(t => t.ApplicationInWorkId == applicationInWorkId)
|
.Where(t => t.ApplicationInWorkId == applicationInWorkId && t.Host!.WorkGroupId != null)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
|
//Группируем шаблоны по рабочим группам
|
||||||
var workGroupsWithTemplates = templates.GroupBy(t => t.Host!.WorkGroupId);
|
var workGroupsWithTemplates = templates.GroupBy(t => t.Host!.WorkGroupId);
|
||||||
|
|
||||||
foreach (var workGroupWithTemplates in workGroupsWithTemplates)
|
foreach (var workGroupWithTemplates in workGroupsWithTemplates)
|
||||||
{
|
{
|
||||||
var wgId = workGroupWithTemplates.Key ?? Guid.NewGuid();//TODO сделать правильно
|
var wgId = (Guid)workGroupWithTemplates.Key!;
|
||||||
var values = workGroupWithTemplates.ToList();
|
var values = workGroupWithTemplates.ToList();
|
||||||
|
|
||||||
if (!values.Any())
|
//Обновляем сразу время при необходимости, так как дальше будем работать только с датой
|
||||||
continue;
|
var timesList = values.Select(t => t.NextRun.TimeOfDay).Distinct().ToList();
|
||||||
|
if (timesList.Count() > 1 || (timesList.Count() == 1 && timesList[0] != appInWork!.ReferenceDate.TimeOfDay))
|
||||||
//Обновляем сразу время при необходимости
|
|
||||||
values.ForEach(t =>
|
|
||||||
{
|
{
|
||||||
if (t.NextRun.TimeOfDay != appInWork!.ReferenceDate.TimeOfDay)
|
values.ForEach(t =>
|
||||||
//t.NextRun = new DateTimeOffset(t.NextRun.DateTime, new TimeSpan(//(appInWork!.ReferenceDate.Hour, appInWork!.ReferenceDate.Minute, appInWork!.ReferenceDate.Second));
|
{
|
||||||
t.NextRun = new DateTimeOffset(t.NextRun.Year, t.NextRun.Month, t.NextRun.Day,
|
if (t.NextRun.TimeOfDay != appInWork!.ReferenceDate.TimeOfDay)
|
||||||
appInWork!.ReferenceDate.Hour, appInWork!.ReferenceDate.Minute, appInWork!.ReferenceDate.Second,
|
t.NextRun = new DateTimeOffset(t.NextRun.Year, t.NextRun.Month, t.NextRun.Day,
|
||||||
new TimeSpan(0, 0, 0));
|
appInWork!.ReferenceDate.Hour, appInWork!.ReferenceDate.Minute, appInWork!.ReferenceDate.Second,
|
||||||
});
|
new TimeSpan(0, 0, 0));
|
||||||
|
});
|
||||||
if (!await applicationsInWorkService.CommitAsync())
|
if (!await templateService.CommitAsync())
|
||||||
{
|
{
|
||||||
logger.LogError($"Ошибка записи изменений в БД при актуализации времени NextRun шаблонов");
|
logger.LogError($"Ошибка записи изменений в БД при актуализации времени NextRun шаблонов РР({applicationInWorkId})");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var distrTemplates = await DistributeTemplateAsync(new List<Template>(), applicationInWorkId, wgId);
|
||||||
var distrTemplates = await DistributeTemplateAsync(values, applicationInWorkId, wgId);
|
|
||||||
|
|
||||||
if (distrTemplates.Any())
|
if (distrTemplates.Any())
|
||||||
if (!await applicationsInWorkService.CommitAsync())
|
if (!await templateService.CommitAsync())
|
||||||
logger.LogError($"Ошибка записи изменений в БД при перераспределении NextRun шаблонов");
|
logger.LogError($"Ошибка записи изменений в БД при перераспределении NextRun шаблонов РР({applicationInWorkId})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +86,12 @@ namespace PARR.TemplateDistributor
|
|||||||
.Include(aiw => aiw.EsppSchValues)
|
.Include(aiw => aiw.EsppSchValues)
|
||||||
.ThenInclude(esv => esv.EsppSchTypeValue)
|
.ThenInclude(esv => esv.EsppSchTypeValue)
|
||||||
.ThenInclude(etv => etv!.DistributionPeriod)
|
.ThenInclude(etv => etv!.DistributionPeriod)
|
||||||
.FirstOrDefaultAsync(t => t.Id == applicationInWorkId);
|
.FirstAsync(t => t.Id == applicationInWorkId);
|
||||||
|
|
||||||
var refDate = appInWork!.ReferenceDate;
|
var refDate = appInWork.ReferenceDate;
|
||||||
|
|
||||||
//Проверяем наличие распределения РР на период
|
//Проверяем наличие распределения РР на период
|
||||||
if (appInWork!.IsAutoDistributionEnabled)
|
if (appInWork.IsAutoDistributionEnabled)
|
||||||
{
|
{
|
||||||
var existingTemplates = await templateService.Get()
|
var existingTemplates = await templateService.Get()
|
||||||
.Include(t => t.Host)
|
.Include(t => t.Host)
|
||||||
@@ -114,10 +99,11 @@ namespace PARR.TemplateDistributor
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
//Удалим из входных шаблонов уже существующие в БД
|
//Удалим из входных шаблонов уже существующие в БД
|
||||||
|
//TODO: сделать селект повторяющихся шаблонов, написать их в варнинг и потом удалить
|
||||||
templates.RemoveAll(t => existingTemplates.Any(et => et.Id == t.Id));
|
templates.RemoveAll(t => existingTemplates.Any(et => et.Id == t.Id));
|
||||||
|
|
||||||
//Если распределенная РР получаем начало
|
//Если распределенная РР получаем начало
|
||||||
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
|
var period = appInWork.EsppSchValues.First()!.EsppSchTypeValue!.DistributionPeriod;
|
||||||
var periodType = ParseDistributionPeriodType(period!.Type);
|
var periodType = ParseDistributionPeriodType(period!.Type);
|
||||||
|
|
||||||
var workDays = await GetWorkDaysAsync(appInWork);
|
var workDays = await GetWorkDaysAsync(appInWork);
|
||||||
@@ -162,7 +148,7 @@ namespace PARR.TemplateDistributor
|
|||||||
|
|
||||||
return templates;
|
return templates;
|
||||||
|
|
||||||
|
#region comments
|
||||||
|
|
||||||
//var d = new Dictionary<DateOnly, List<Template>>();
|
//var d = new Dictionary<DateOnly, List<Template>>();
|
||||||
//foreach (var wd in workDays)
|
//foreach (var wd in workDays)
|
||||||
@@ -233,6 +219,8 @@ namespace PARR.TemplateDistributor
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate);
|
templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate);
|
||||||
@@ -240,7 +228,12 @@ namespace PARR.TemplateDistributor
|
|||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork)
|
/// <summary>
|
||||||
|
/// Получить список рабочих дней из календаря и перенести прошедшие даты на следующий период по РР
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appInWork"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork)
|
||||||
{
|
{
|
||||||
|
|
||||||
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
|
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
|
||||||
@@ -255,6 +248,7 @@ namespace PARR.TemplateDistributor
|
|||||||
wd.Year, wd.Month, wd.Day,
|
wd.Year, wd.Month, wd.Day,
|
||||||
appInWork.ReferenceDate.Hour, appInWork.ReferenceDate.Minute, appInWork.ReferenceDate.Second,
|
appInWork.ReferenceDate.Hour, appInWork.ReferenceDate.Minute, appInWork.ReferenceDate.Second,
|
||||||
new TimeSpan(0, 0, 0));
|
new TimeSpan(0, 0, 0));
|
||||||
|
|
||||||
if (wrokDateTimeOffset < DateTimeOffset.UtcNow)
|
if (wrokDateTimeOffset < DateTimeOffset.UtcNow)
|
||||||
{
|
{
|
||||||
wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration);
|
wrokDateTimeOffset = esppScheduleTransformService.GetNextDateForDistributionRun(wrokDateTimeOffset, periodType, period.Duration);
|
||||||
@@ -265,16 +259,19 @@ namespace PARR.TemplateDistributor
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверить соответствие распределения существующих шаблонов нововму плану.
|
||||||
|
/// На выходе получаем шаблоны, которым требуется изменить дату следующего запуска.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="distributionPlan"></param>
|
||||||
|
/// <param name="templates"></param>
|
||||||
|
/// <returns></returns>
|
||||||
private List<Template> GetTemplatesToDistribute(ref Dictionary<DateOnly, int> distributionPlan, List<Template> templates)
|
private List<Template> GetTemplatesToDistribute(ref Dictionary<DateOnly, int> distributionPlan, List<Template> templates)
|
||||||
{
|
{
|
||||||
var result = new List<Template>();
|
var result = new List<Template>();
|
||||||
|
|
||||||
foreach (var wd in distributionPlan)
|
foreach (var wd in distributionPlan)
|
||||||
{
|
{
|
||||||
//if (wd.Value < 1)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
var templatesInWd = templates.Where(t => DateOnly.FromDateTime(t.NextRun.DateTime) == wd.Key).ToList();
|
var templatesInWd = templates.Where(t => DateOnly.FromDateTime(t.NextRun.DateTime) == wd.Key).ToList();
|
||||||
var templatesToDistribute = templatesInWd.Skip(wd.Value).Take(templatesInWd.Count - wd.Value).ToList();
|
var templatesToDistribute = templatesInWd.Skip(wd.Value).Take(templatesInWd.Count - wd.Value).ToList();
|
||||||
|
|
||||||
@@ -303,48 +300,51 @@ namespace PARR.TemplateDistributor
|
|||||||
|
|
||||||
private Dictionary<DateOnly, int> GetDistributionPlan(List<DateOnly> workDays, int templateCount)
|
private Dictionary<DateOnly, int> GetDistributionPlan(List<DateOnly> workDays, int templateCount)
|
||||||
{
|
{
|
||||||
var d = new Dictionary<DateOnly, int>();
|
var result = new Dictionary<DateOnly, int>();
|
||||||
|
//Заполняем будующий план датами из полученных на входе данных
|
||||||
foreach (var wd in workDays)
|
foreach (var wd in workDays)
|
||||||
{
|
{
|
||||||
var workDateTimeOffset = new DateOnly(wd.Year, wd.Month, wd.Day);
|
var workDate = new DateOnly(wd.Year, wd.Month, wd.Day);
|
||||||
d.Add(workDateTimeOffset, 0);
|
result.Add(workDate, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var templateDistributed = 0;
|
var templateDistributedCount = 0;//количество распределённых на текущий момент шаблонов
|
||||||
|
|
||||||
if (templateCount >= workDays.Count)
|
//Если количество шаблонов больше количества рабочих дней, то сразу распределяем их равным количеством по всем рабочим дням
|
||||||
|
if (templateDistributedCount >= workDays.Count)
|
||||||
{
|
{
|
||||||
|
//количеством шаблонов на один рабочий день
|
||||||
var mainPartTemplateCountToDistribute = templateCount / workDays.Count;
|
var mainPartTemplateCountToDistribute = templateCount / workDays.Count;
|
||||||
foreach (var item in d)
|
|
||||||
{
|
|
||||||
d[item.Key] = mainPartTemplateCountToDistribute;
|
|
||||||
|
|
||||||
templateDistributed += mainPartTemplateCountToDistribute;
|
//перебираем рабочие дня и записываем количество шаблонов
|
||||||
|
foreach (var item in result)
|
||||||
|
{
|
||||||
|
result[item.Key] = mainPartTemplateCountToDistribute;
|
||||||
|
|
||||||
|
templateDistributedCount += mainPartTemplateCountToDistribute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var daysBetweenTemplates = (double)workDays.Count / (templateCount % workDays.Count);//количество дней между шаблонами, если распределить их равномерно
|
||||||
|
var currentStepBetweenTemplates = (double)Math.Floor(daysBetweenTemplates);//инициализация шага перехода между датами запуска двух шаблонов
|
||||||
|
var balance = (double)daysBetweenTemplates - Math.Floor(currentStepBetweenTemplates);//остаток между датами, потому что мы берём целые дни, его нужно учесть в следующей итирации
|
||||||
|
var currentDayIndex = 0;//инициализация индекса даты словаря рабочих дней
|
||||||
|
|
||||||
var templatesPerWorkDay = (double)workDays.Count / (templateCount % workDays.Count);
|
while (templateDistributedCount < templateCount)
|
||||||
var currentStep = (double)Math.Floor(templatesPerWorkDay);//??????? точно double?
|
|
||||||
var balance = (double)templatesPerWorkDay - Math.Floor(currentStep);
|
|
||||||
var currentIndex = 0;
|
|
||||||
|
|
||||||
while (templateDistributed < templateCount)
|
|
||||||
{
|
{
|
||||||
if (currentStep > 0)
|
//лишняя проверка так как шагом ранее мы распределям шаблоны равным количеством и currentStepBetweenTemplates не может быть меньше одного дня
|
||||||
{
|
//if (currentStepBetweenTemplates > 0)
|
||||||
d[d.ElementAt(currentIndex).Key] += 1;
|
//{
|
||||||
templateDistributed++;
|
result[result.ElementAt(currentDayIndex).Key] += 1;
|
||||||
currentIndex += (int)Math.Floor(currentStep);
|
templateDistributedCount++;
|
||||||
|
currentDayIndex += (int)Math.Floor(currentStepBetweenTemplates);
|
||||||
|
//}
|
||||||
|
|
||||||
|
currentStepBetweenTemplates = daysBetweenTemplates + balance;
|
||||||
}
|
balance = daysBetweenTemplates - currentStepBetweenTemplates;
|
||||||
|
|
||||||
currentStep = templatesPerWorkDay + balance;
|
|
||||||
balance = templatesPerWorkDay - currentStep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
<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.EsppApi\PARR.EsppApi.csproj" />
|
<ProjectReference Include="..\PARR.EsppApi\PARR.EsppApi.csproj" />
|
||||||
|
<ProjectReference Include="..\PARR.TemplateDistributor\PARR.TemplateDistributor.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using PARR.EsppApi;
|
|||||||
using PARR.DAL;
|
using PARR.DAL;
|
||||||
using PARR.Test;
|
using PARR.Test;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using PARR.TemplateDistributor;
|
||||||
|
|
||||||
IHost host = Host.CreateDefaultBuilder(args)
|
IHost host = Host.CreateDefaultBuilder(args)
|
||||||
.ConfigureServices((hostContext, services) =>
|
.ConfigureServices((hostContext, services) =>
|
||||||
@@ -10,6 +11,7 @@ IHost host = Host.CreateDefaultBuilder(args)
|
|||||||
services.InstallEsppApiServices(hostContext.Configuration);
|
services.InstallEsppApiServices(hostContext.Configuration);
|
||||||
services.InstallBllServices(hostContext.Configuration);
|
services.InstallBllServices(hostContext.Configuration);
|
||||||
services.InstallDalServices(hostContext.Configuration);
|
services.InstallDalServices(hostContext.Configuration);
|
||||||
|
services.InstallTemplateDistributorSerivces(hostContext.Configuration);
|
||||||
|
|
||||||
services.AddHostedService<Worker>();
|
services.AddHostedService<Worker>();
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user