refactor(templateMatcher):
- унификация деактивации шаблонов между разными синхронизаторами - поиск ЭК выделен в отдельную сущность
This commit is contained in:
@@ -21,5 +21,15 @@
|
||||
/// Значение тега, обозначающее неиспользуемый юнит.
|
||||
/// </summary>
|
||||
public const string NotUsedTagValue = "ПАРР-НЕИСП";
|
||||
|
||||
/// <summary>
|
||||
/// Состояние шаблонов по-умолчанию
|
||||
/// </summary>
|
||||
public const bool DefaultUnusedTemplateState = false;
|
||||
|
||||
/// <summary>
|
||||
/// Состояние расписаний по-умолчанию
|
||||
/// </summary>
|
||||
public const bool DefaultUnusedScheduleState = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class BuildGroupsStage : IGroupedSyncStage
|
||||
{
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class DeactivateTemplatesStage : IGroupedSyncWriteStage
|
||||
{
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
private readonly ITemplateDeactivator _deactivator;
|
||||
private readonly IUnusedTemplateTargetUnitResolver _targetUnitResolver;
|
||||
private readonly ILogger<DeactivateTemplatesStage> _logger;
|
||||
|
||||
public string StageName => "Деактивация шаблонов";
|
||||
@@ -18,16 +18,22 @@ internal class DeactivateTemplatesStage : IGroupedSyncWriteStage
|
||||
public DeactivateTemplatesStage(
|
||||
ITemplateRepository templateRepository,
|
||||
ITemplateDeactivator deactivator,
|
||||
IUnusedTemplateTargetUnitResolver targetUnitResolver,
|
||||
ILogger<DeactivateTemplatesStage> logger)
|
||||
{
|
||||
_templateRepository = templateRepository;
|
||||
_deactivator = deactivator;
|
||||
_targetUnitResolver = targetUnitResolver;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<GroupedSyncContext> ExecuteAsync(GroupedSyncContext context, CancellationToken ct = default)
|
||||
public async Task<GroupedSyncContext> ExecuteAsync(
|
||||
GroupedSyncContext context,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var allJobIds = context.JobsInGroup.Select(j => j.Id).ToHashSet();
|
||||
var allJobIds = context.JobsInGroup
|
||||
.Select(j => j.Id)
|
||||
.ToHashSet();
|
||||
|
||||
var existingTemplates = await _templateRepository.Get()
|
||||
.AsNoTracking()
|
||||
@@ -39,45 +45,76 @@ internal class DeactivateTemplatesStage : IGroupedSyncWriteStage
|
||||
&& t.Job!.GroupId == context.JobGroupId)
|
||||
.ToListAsync(ct);
|
||||
|
||||
int deactivated = 0;
|
||||
foreach (var template in existingTemplates)
|
||||
var staleTemplates = existingTemplates
|
||||
.Where(t => !context.ExpectedTemplateKeys.Contains(
|
||||
(t.JobId, t.UnitId, t.Index ?? -1)))
|
||||
.ToList();
|
||||
|
||||
if (staleTemplates.Count == 0)
|
||||
{
|
||||
var key = (template.JobId, template.UnitId, template.Index ?? -1);
|
||||
if (!context.ExpectedTemplateKeys.Contains(key))
|
||||
_logger.LogDebug(
|
||||
"JobGroup '{JobGroupName}' ({JobGroupId}): шаблонов для деактивации нет.",
|
||||
context.JobGroupName,
|
||||
context.JobGroupId);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
var targetUnits = await _targetUnitResolver.ResolveAsync(staleTemplates, ct);
|
||||
|
||||
int deactivated = 0;
|
||||
|
||||
foreach (var template in staleTemplates)
|
||||
{
|
||||
var unitLogName = context.UnitNames.TryGetValue(template.UnitId, out var unitName)
|
||||
? $"'{unitName}' ({template.UnitId})"
|
||||
: template.Unit != null
|
||||
? $"'{template.Unit.Name}' ({template.UnitId})"
|
||||
: $"({template.UnitId})";
|
||||
|
||||
_logger.LogInformation(
|
||||
"JobGroup '{JobGroupName}' ({JobGroupId}): деактивация шаблона '{TemplateName}' ({TemplateId}), Job '{JobName}' ({JobId}), Unit {Unit}",
|
||||
context.JobGroupName,
|
||||
context.JobGroupId,
|
||||
template.Name,
|
||||
template.Id,
|
||||
template.Job?.Name ?? string.Empty,
|
||||
template.JobId,
|
||||
unitLogName);
|
||||
|
||||
if (!targetUnits.TryGetValue(template.Id, out var targetUnit))
|
||||
{
|
||||
var unitLogName = context.UnitNames.TryGetValue(template.UnitId, out var unitName)
|
||||
? $"'{unitName}' ({template.UnitId})"
|
||||
: template.Unit != null
|
||||
? $"'{template.Unit.Name}' ({template.UnitId})"
|
||||
: $"({template.UnitId})";
|
||||
_logger.LogError(
|
||||
"Не удалось определить целевой Unit для деактивации шаблона {TemplateId}.",
|
||||
template.Id);
|
||||
|
||||
_logger.LogInformation(
|
||||
"JobGroup '{JobGroupName}' ({JobGroupId}): деактивация шаблона '{TemplateName}' ({TemplateId}), Job '{JobName}' ({JobId}), Unit {Unit}",
|
||||
context.JobGroupName, context.JobGroupId,
|
||||
template.Name, template.Id,
|
||||
template.Job?.Name ?? string.Empty, template.JobId,
|
||||
unitLogName);
|
||||
continue;
|
||||
}
|
||||
|
||||
var success = await _deactivator.DeactivateTemplateAsync(template, context.Initiator);
|
||||
var success = await _deactivator.DeactivateTemplateAsync(
|
||||
template,
|
||||
targetUnit,
|
||||
context.Initiator,
|
||||
ct);
|
||||
|
||||
if (success)
|
||||
{
|
||||
deactivated++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError(
|
||||
"JobGroup '{JobGroupName}' ({JobGroupId}): не удалось деактивировать шаблон '{TemplateName}' ({TemplateId}).",
|
||||
context.JobGroupName,
|
||||
context.JobGroupId,
|
||||
template.Name,
|
||||
template.Id);
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
deactivated++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError(
|
||||
"Не удалось деактивировать шаблон {TemplateId}.",
|
||||
template.Id);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogDebug("JobGroup '{JobGroupName}' ({JobGroupId}): деактивировано {Count} шаблонов из {Total}",
|
||||
context.JobGroupName, context.JobGroupId, deactivated, existingTemplates.Count);
|
||||
_logger.LogDebug(
|
||||
"JobGroup '{JobGroupName}' ({JobGroupId}): деактивировано {Count} шаблонов из {Total}",
|
||||
context.JobGroupName,
|
||||
context.JobGroupId,
|
||||
deactivated,
|
||||
staleTemplates.Count);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Services.UnitFilterService;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class FilterUnitsStage : IGroupedSyncStage
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class GroupFilterStage : IGroupedSyncStage
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ using PARR.Domain.Entities.JobEntities;
|
||||
using PARR.Domain.Entities.JobGroupEntities;
|
||||
using PARR.TemplateMatcher.Models;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
/// <summary>
|
||||
/// Контекст групповой синхронизации. Передаётся между этапами.
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync
|
||||
{
|
||||
/// <summary>
|
||||
/// Этап групповой синхронизации, который только читает данные.
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces.JobGroupRepositories;
|
||||
using PARR.TemplateMatcher.Exceptions;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class LoadJobGroupStage : IGroupedSyncStage
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class ProcessGroupsStage : IGroupedSyncWriteStage
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
namespace PARR.TemplateMatcher.Services.GroupedSync;
|
||||
|
||||
internal class ResolveConflictsStage : IGroupedSyncStage
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Exceptions;
|
||||
using PARR.TemplateMatcher.Services.GroupedSync;
|
||||
using PARR.TemplateMatcher.Services.Implementations.GroupedSync;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces.JobRepositories;
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.JobEntities;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.Domain.Settings;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
@@ -16,106 +16,113 @@ namespace PARR.TemplateMatcher.Services.Implementations;
|
||||
|
||||
internal class TemplateDeactivator : ITemplateDeactivator
|
||||
{
|
||||
private const bool DefaultUnusedTemplateState = false;
|
||||
private const bool DefaultUnusedScheduleState = false;
|
||||
private readonly ILogger<TemplateDeactivator> _logger;
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
private readonly IJobRepository _jobRepository;
|
||||
private readonly ITemplateMqPublisher _templateMqPublisher;
|
||||
private readonly IUnusedTemplateMessageFactory _unusedTemplateMessageFactory;
|
||||
private readonly SettingsFromDb _settingsFromDb;
|
||||
private readonly IOptions<TemplateSettings> _templateSettings;
|
||||
|
||||
private readonly ILogger<TemplateDeactivator> logger;
|
||||
private readonly ITemplateRepository templateService;
|
||||
private readonly IJobRepository jobService;
|
||||
private readonly ITemplateNameNormalizer namenormalizer;
|
||||
private readonly ITemplateMqPublisher templateMqPublisher;
|
||||
private readonly SettingsFromDb settingsFromDb;
|
||||
private readonly IOptions<TemplateSettings> templateSettings;
|
||||
private Job? _unusedJob;
|
||||
|
||||
public TemplateDeactivator(
|
||||
ILogger<TemplateDeactivator> logger,
|
||||
ITemplateRepository templateService,
|
||||
IJobRepository jobService,
|
||||
ITemplateNameNormalizer namenormalizer,
|
||||
ITemplateRepository templateRepository,
|
||||
IJobRepository jobRepository,
|
||||
ITemplateMqPublisher templateMqPublisher,
|
||||
IUnusedTemplateMessageFactory unusedTemplateMessageFactory,
|
||||
SettingsFromDb settingsFromDb,
|
||||
IOptions<TemplateSettings> templateSettings
|
||||
)
|
||||
IOptions<TemplateSettings> templateSettings)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.templateService = templateService;
|
||||
this.jobService = jobService;
|
||||
this.namenormalizer = namenormalizer;
|
||||
this.templateMqPublisher = templateMqPublisher;
|
||||
this.settingsFromDb = settingsFromDb;
|
||||
this.templateSettings = templateSettings;
|
||||
_logger = logger;
|
||||
_templateRepository = templateRepository;
|
||||
_jobRepository = jobRepository;
|
||||
_templateMqPublisher = templateMqPublisher;
|
||||
_unusedTemplateMessageFactory = unusedTemplateMessageFactory;
|
||||
_settingsFromDb = settingsFromDb;
|
||||
_templateSettings = templateSettings;
|
||||
}
|
||||
|
||||
public async Task<bool> DeactivateTemplateAsync(Template template, HistoryInitiator initiator)
|
||||
public async Task<bool> DeactivateTemplateAsync(
|
||||
Template template,
|
||||
Unit targetUnit,
|
||||
HistoryInitiator initiator,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
||||
return true;
|
||||
|
||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
||||
{
|
||||
logger.LogDebug("Шаблон {TemplateId} уже неактивен (Unused), пропускаем деактивацию.", template.Id);
|
||||
_logger.LogDebug(
|
||||
"Шаблон {TemplateId} уже находится в статусе Unused. Пропускаем деактивацию.",
|
||||
template.Id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.LogInformation("Шаблон {TemplateId} (UnitId {UnitId}) → деактивация.",
|
||||
template.Id, template.UnitId);
|
||||
if (template.StatusTypeId == TemplateStatusTypeEnum.Updating)
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Шаблон {TemplateId} уже находится в статусе Updating. Пропускаем повторную деактивацию.",
|
||||
template.Id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var unusedJob = await GetUnusedJobAsync(ct);
|
||||
|
||||
if (unusedJob == null)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Job для неиспользуемых шаблонов не найден. Шаблон {TemplateId} не деактивирован.",
|
||||
template.Id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Деактивация шаблона {TemplateId}. Текущий UnitId: {CurrentUnitId}, целевой UnitId: {TargetUnitId}.",
|
||||
template.Id,
|
||||
template.UnitId,
|
||||
targetUnit.Id);
|
||||
|
||||
template.StatusTypeId = TemplateStatusTypeEnum.Updating;
|
||||
template.DateModified = DateTimeOffset.UtcNow;
|
||||
|
||||
if (!await templateService.CommitAsync(initiator))
|
||||
if (!await _templateRepository.CommitAsync(initiator))
|
||||
{
|
||||
logger.LogError("Не удалось перевести шаблон {TemplateId} в Updating.", template.Id);
|
||||
_logger.LogError(
|
||||
"Не удалось перевести шаблон {TemplateId} в статус Updating.",
|
||||
template.Id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var unusedJob = await jobService.Get()
|
||||
var updateRequest = await _unusedTemplateMessageFactory.CreateAsync(
|
||||
template,
|
||||
unusedJob,
|
||||
targetUnit,
|
||||
initiator,
|
||||
ct);
|
||||
|
||||
await _templateMqPublisher.PublishUpdateAsync(updateRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<Job?> GetUnusedJobAsync(CancellationToken ct)
|
||||
{
|
||||
if (_unusedJob != null)
|
||||
return _unusedJob;
|
||||
|
||||
_unusedJob = await _jobRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Include(j => j.Tnk)
|
||||
.Include(j => j.Group)
|
||||
.ThenInclude(g => g!.GroupType)
|
||||
.FirstOrDefaultAsync(j => j.Id == settingsFromDb.JobIdForUnusedTemplates);
|
||||
.FirstOrDefaultAsync(
|
||||
j => j.Id == _settingsFromDb.JobIdForUnusedTemplates,
|
||||
ct);
|
||||
|
||||
|
||||
if (unusedJob == null)
|
||||
{
|
||||
logger.LogError("Job для деактивированных шаблонов не найден.");
|
||||
return false;
|
||||
}
|
||||
|
||||
unusedJob.TemplateNameMask = templateSettings.Value.UnusedTemplateNameMask;
|
||||
|
||||
// === Создаём временный Template для нормализации имени ===
|
||||
var tempTemplateForName = new Template
|
||||
{
|
||||
Id = template.Id,
|
||||
Name = template.Name,
|
||||
JobId = unusedJob.Id,
|
||||
UnitId = template.UnitId,
|
||||
Index = template.Index,
|
||||
Job = unusedJob,
|
||||
Unit = template.Unit,
|
||||
UnitsInTemplate = new List<UnitsInTemplate>()
|
||||
};
|
||||
|
||||
var expectedName = await namenormalizer.GetNormalizedTemplateNameAsync(tempTemplateForName);
|
||||
|
||||
var updateRequest = new TemplateUpdaterMessage
|
||||
{
|
||||
TemplateId = template.Id,
|
||||
JobId = unusedJob.Id,
|
||||
UnitId = template.UnitId,
|
||||
Name = expectedName,
|
||||
IsActiveTemplate = DefaultUnusedTemplateState,
|
||||
IsActiveSchedule = DefaultUnusedScheduleState,
|
||||
IsNew = false,
|
||||
Index = template.Index,
|
||||
StatusTypeId = TemplateStatusTypeEnum.Unused,
|
||||
Initiator = initiator,
|
||||
UnitsInTemplate = new List<UnitInTemplateMessage>()
|
||||
};
|
||||
|
||||
await templateMqPublisher.PublishUpdateAsync(updateRequest);
|
||||
return true;
|
||||
return _unusedJob;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.JobEntities;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Constants;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using PARR.TemplateMatcher.Settings;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||
|
||||
internal class UnusedTemplateMessageFactory : IUnusedTemplateMessageFactory
|
||||
{
|
||||
private readonly ITemplateNameNormalizer _templateNameNormalizer;
|
||||
private readonly IOptions<TemplateSettings> _templateSettings;
|
||||
|
||||
public UnusedTemplateMessageFactory(
|
||||
ITemplateNameNormalizer templateNameNormalizer,
|
||||
IOptions<TemplateSettings> templateSettings)
|
||||
{
|
||||
_templateNameNormalizer = templateNameNormalizer;
|
||||
_templateSettings = templateSettings;
|
||||
}
|
||||
|
||||
public async Task<TemplateUpdaterMessage> CreateAsync(
|
||||
Template template,
|
||||
Job unusedJob,
|
||||
Unit targetUnit,
|
||||
HistoryInitiator initiator,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var jobForName = new Job
|
||||
{
|
||||
Id = unusedJob.Id,
|
||||
Name = unusedJob.Name,
|
||||
WorkName = unusedJob.WorkName,
|
||||
MinValueRelationships = unusedJob.MinValueRelationships,
|
||||
MaxValueRelationships = unusedJob.MaxValueRelationships,
|
||||
IsParentRelationships = unusedJob.IsParentRelationships,
|
||||
TemplateNameMask = _templateSettings.Value.UnusedTemplateNameMask,
|
||||
WorkGroupMask = unusedJob.WorkGroupMask,
|
||||
ResponseAreaMask = unusedJob.ResponseAreaMask,
|
||||
TnkId = unusedJob.TnkId,
|
||||
GroupId = unusedJob.GroupId,
|
||||
Group = unusedJob.Group,
|
||||
Tnk = unusedJob.Tnk,
|
||||
UnitFilters = unusedJob.UnitFilters,
|
||||
Templates = unusedJob.Templates,
|
||||
AutoControl = unusedJob.AutoControl
|
||||
};
|
||||
|
||||
var templateForName = new Template
|
||||
{
|
||||
Id = template.Id,
|
||||
Name = template.Name,
|
||||
JobId = unusedJob.Id,
|
||||
UnitId = targetUnit.Id,
|
||||
Index = null,
|
||||
Job = jobForName,
|
||||
Unit = targetUnit,
|
||||
UnitsInTemplate = new List<UnitsInTemplate>()
|
||||
};
|
||||
|
||||
var expectedName = await _templateNameNormalizer.GetNormalizedTemplateNameAsync(templateForName);
|
||||
|
||||
return new TemplateUpdaterMessage
|
||||
{
|
||||
TemplateId = template.Id,
|
||||
JobId = unusedJob.Id,
|
||||
UnitId = targetUnit.Id,
|
||||
Name = expectedName,
|
||||
IsActiveTemplate = UnusedTemplateConstants.DefaultUnusedTemplateState,
|
||||
IsActiveSchedule = UnusedTemplateConstants.DefaultUnusedScheduleState,
|
||||
IsNew = false,
|
||||
Index = null,
|
||||
StatusTypeId = TemplateStatusTypeEnum.Unused,
|
||||
Initiator = initiator,
|
||||
UnitsInTemplate = new List<UnitInTemplateMessage>()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces.Unit;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
using PARR.TemplateMatcher.Constants;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations;
|
||||
|
||||
internal class UnusedTemplateTargetUnitResolver : IUnusedTemplateTargetUnitResolver
|
||||
{
|
||||
private readonly IUnitFieldRepository _unitFieldRepository;
|
||||
private readonly IUnitInValueRepository _unitInValueRepository;
|
||||
private readonly IUnitRepository _unitRepository;
|
||||
private readonly ILogger<UnusedTemplateTargetUnitResolver> _logger;
|
||||
|
||||
public UnusedTemplateTargetUnitResolver(
|
||||
IUnitFieldRepository unitFieldRepository,
|
||||
IUnitInValueRepository unitInValueRepository,
|
||||
IUnitRepository unitRepository,
|
||||
ILogger<UnusedTemplateTargetUnitResolver> logger)
|
||||
{
|
||||
_unitFieldRepository = unitFieldRepository;
|
||||
_unitInValueRepository = unitInValueRepository;
|
||||
_unitRepository = unitRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyDictionary<Guid, Unit>> ResolveAsync(
|
||||
IReadOnlyCollection<Template> templates,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var result = new Dictionary<Guid, Unit>();
|
||||
|
||||
foreach (var template in templates.Where(t => t.Unit != null))
|
||||
{
|
||||
result[template.Id] = template.Unit!;
|
||||
}
|
||||
|
||||
if (templates.Count == 0)
|
||||
return result;
|
||||
|
||||
var responsableAreaField = await _unitFieldRepository.GetByAihitNameAsync(
|
||||
UnusedTemplateConstants.ResponsibilityAreaFieldName,
|
||||
ct);
|
||||
|
||||
var tagField = await _unitFieldRepository.GetByAihitNameAsync(
|
||||
UnusedTemplateConstants.ParrTagFieldName,
|
||||
ct);
|
||||
|
||||
if (responsableAreaField == null || tagField == null)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Не найдены поля '{ResponsibilityAreaField}' или '{TagField}'. Целевой Unit для неиспользуемых шаблонов будет выбран как текущий.",
|
||||
UnusedTemplateConstants.ResponsibilityAreaFieldName,
|
||||
UnusedTemplateConstants.ParrTagFieldName);
|
||||
|
||||
await AddFallbackUnitsAsync(templates, result, ct);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var targetTagValueId = await _unitInValueRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(uiv => uiv.FieldId == tagField.Id
|
||||
&& uiv.Value != null
|
||||
&& uiv.Value.Value == UnusedTemplateConstants.NotUsedTagValue)
|
||||
.Select(uiv => uiv.ValueId)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
if (targetTagValueId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Значение '{TagValue}' для поля '{FieldName}' не найдено. Целевой Unit для неиспользуемых шаблонов будет выбран как текущий.",
|
||||
UnusedTemplateConstants.NotUsedTagValue,
|
||||
UnusedTemplateConstants.ParrTagFieldName);
|
||||
|
||||
await AddFallbackUnitsAsync(templates, result, ct);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var unitIds = templates
|
||||
.Select(t => t.UnitId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var unitResponsableAreaValues = await _unitInValueRepository.GetByUnitIdsAndFieldIdsAsync(
|
||||
unitIds,
|
||||
new List<Guid> { responsableAreaField.Id },
|
||||
ct);
|
||||
|
||||
var unitToResponsableAreaValueMap = unitResponsableAreaValues
|
||||
.Where(uiv => uiv.ValueId != Guid.Empty)
|
||||
.ToDictionary(uiv => uiv.UnitId, uiv => uiv.ValueId);
|
||||
|
||||
if (unitToResponsableAreaValueMap.Count == 0)
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Для юнитов не найдены значения поля '{FieldName}'. Целевой Unit для неиспользуемых шаблонов будет выбран как текущий.",
|
||||
UnusedTemplateConstants.ResponsibilityAreaFieldName);
|
||||
|
||||
await AddFallbackUnitsAsync(templates, result, ct);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var distinctResponsableAreaValues = unitToResponsableAreaValueMap.Values
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var matches = await _unitInValueRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(uiv => uiv.FieldId == responsableAreaField.Id
|
||||
&& distinctResponsableAreaValues.Contains(uiv.ValueId))
|
||||
.Join(
|
||||
_unitInValueRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(t => t.FieldId == tagField.Id && t.ValueId == targetTagValueId),
|
||||
responsableArea => responsableArea.UnitId,
|
||||
tag => tag.UnitId,
|
||||
(responsableArea, tag) => new
|
||||
{
|
||||
responsableArea.ValueId,
|
||||
responsableArea.UnitId
|
||||
})
|
||||
.ToListAsync(ct);
|
||||
|
||||
var responsableAreaToTargetUnitMap = matches
|
||||
.GroupBy(x => x.ValueId)
|
||||
.ToDictionary(g => g.Key, g => g.First().UnitId);
|
||||
|
||||
var templatesToReload = new Dictionary<Guid, Guid>();
|
||||
|
||||
foreach (var template in templates)
|
||||
{
|
||||
if (!unitToResponsableAreaValueMap.TryGetValue(template.UnitId, out var responsableAreaValueId))
|
||||
continue;
|
||||
|
||||
if (!responsableAreaToTargetUnitMap.TryGetValue(responsableAreaValueId, out var targetUnitId))
|
||||
continue;
|
||||
|
||||
if (targetUnitId == Guid.Empty || targetUnitId == template.UnitId)
|
||||
continue;
|
||||
|
||||
templatesToReload[template.Id] = targetUnitId;
|
||||
}
|
||||
|
||||
if (templatesToReload.Count > 0)
|
||||
{
|
||||
var targetUnitIds = templatesToReload.Values
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var targetUnits = await _unitRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(u => targetUnitIds.Contains(u.Id))
|
||||
.ToDictionaryAsync(u => u.Id, ct);
|
||||
|
||||
foreach (var kvp in templatesToReload)
|
||||
{
|
||||
if (targetUnits.TryGetValue(kvp.Value, out var targetUnit))
|
||||
{
|
||||
result[kvp.Key] = targetUnit;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Не удалось загрузить целевой Unit {TargetUnitId} для шаблона {TemplateId}.",
|
||||
kvp.Value,
|
||||
kvp.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await AddFallbackUnitsAsync(templates, result, ct);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task AddFallbackUnitsAsync(
|
||||
IReadOnlyCollection<Template> templates,
|
||||
Dictionary<Guid, Unit> result,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var missingUnitIds = templates
|
||||
.Where(t => !result.ContainsKey(t.Id) && t.UnitId != Guid.Empty)
|
||||
.Select(t => t.UnitId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
if (missingUnitIds.Count == 0)
|
||||
return;
|
||||
|
||||
var fallbackUnits = await _unitRepository.Get()
|
||||
.AsNoTracking()
|
||||
.Where(u => missingUnitIds.Contains(u.Id))
|
||||
.ToDictionaryAsync(u => u.Id, ct);
|
||||
|
||||
foreach (var template in templates.Where(t => !result.ContainsKey(t.Id) && t.UnitId != Guid.Empty))
|
||||
{
|
||||
if (fallbackUnits.TryGetValue(template.UnitId, out var fallbackUnit))
|
||||
{
|
||||
result[template.Id] = fallbackUnit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Interfaces
|
||||
{
|
||||
public interface ITemplateDeactivator
|
||||
{
|
||||
Task<bool> DeactivateTemplateAsync(Template template, HistoryInitiator initiator);
|
||||
Task<bool> DeactivateTemplateAsync(
|
||||
Template template,
|
||||
Unit targetUnit,
|
||||
HistoryInitiator initiator,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.JobEntities;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Interfaces
|
||||
{
|
||||
internal interface IUnusedTemplateMessageFactory
|
||||
{
|
||||
Task<TemplateUpdaterMessage> CreateAsync(
|
||||
Template template,
|
||||
Job unusedJob,
|
||||
Unit targetUnit,
|
||||
HistoryInitiator initiator,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using PARR.Domain.Entities;
|
||||
using PARR.Domain.Entities.Unit;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Interfaces
|
||||
{
|
||||
internal interface IUnusedTemplateTargetUnitResolver
|
||||
{
|
||||
Task<IReadOnlyDictionary<Guid, Unit>> ResolveAsync(
|
||||
IReadOnlyCollection<Template> templates,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.TemplateMatcher.Models;
|
||||
using PARR.TemplateMatcher.Services.Implementations;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class AllocateTemplatesStage : ISimpleSyncWriteStage
|
||||
{
|
||||
|
||||
@@ -3,9 +3,8 @@ using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class AnalyzeChangesStage : ISimpleSyncStage
|
||||
{
|
||||
|
||||
@@ -1,33 +1,81 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class DeactivateTemplatesStage : ISimpleSyncWriteStage
|
||||
{
|
||||
private readonly ITemplateDeactivator _deactivator;
|
||||
private readonly IUnusedTemplateTargetUnitResolver _targetUnitResolver;
|
||||
private readonly ILogger<DeactivateTemplatesStage> _logger;
|
||||
|
||||
public string StageName => "Деактивация шаблонов";
|
||||
|
||||
public DeactivateTemplatesStage(ITemplateDeactivator deactivator, ILogger<DeactivateTemplatesStage> logger)
|
||||
public DeactivateTemplatesStage(
|
||||
ITemplateDeactivator deactivator,
|
||||
IUnusedTemplateTargetUnitResolver targetUnitResolver,
|
||||
ILogger<DeactivateTemplatesStage> logger)
|
||||
{
|
||||
_deactivator = deactivator;
|
||||
_targetUnitResolver = targetUnitResolver;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<SimpleSyncContext> ExecuteAsync(SimpleSyncContext context, CancellationToken ct = default)
|
||||
public async Task<SimpleSyncContext> ExecuteAsync(
|
||||
SimpleSyncContext context,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
if (!context.UnusedTemplates.Any())
|
||||
return context;
|
||||
|
||||
var targetUnits = await _targetUnitResolver.ResolveAsync(context.UnusedTemplates, ct);
|
||||
|
||||
int deactivated = 0;
|
||||
|
||||
foreach (var template in context.UnusedTemplates)
|
||||
{
|
||||
_logger.LogInformation("Job '{JobName}' ({JobId}): деактивация шаблона '{TemplateName}' ({TemplateId}), Unit {Unit}",
|
||||
context.JobName, context.JobId, template.Name, template.Id,
|
||||
_logger.LogInformation(
|
||||
"Job '{JobName}' ({JobId}): деактивация шаблона '{TemplateName}' ({TemplateId}), Unit {Unit}",
|
||||
context.JobName,
|
||||
context.JobId,
|
||||
template.Name,
|
||||
template.Id,
|
||||
context.FormatUnit(template.UnitId));
|
||||
|
||||
await _deactivator.DeactivateTemplateAsync(template, context.Initiator);
|
||||
if (!targetUnits.TryGetValue(template.Id, out var targetUnit))
|
||||
{
|
||||
_logger.LogError(
|
||||
"Не удалось определить целевой Unit для деактивации шаблона {TemplateId}.",
|
||||
template.Id);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var success = await _deactivator.DeactivateTemplateAsync(
|
||||
template,
|
||||
targetUnit,
|
||||
context.Initiator,
|
||||
ct);
|
||||
|
||||
if (success)
|
||||
{
|
||||
deactivated++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError(
|
||||
"Не удалось деактивировать шаблон {TemplateId}.",
|
||||
template.Id);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogDebug(
|
||||
"Job '{JobName}' ({JobId}): деактивировано {Count} шаблонов из {Total}.",
|
||||
context.JobName,
|
||||
context.JobId,
|
||||
deactivated,
|
||||
context.UnusedTemplates.Count);
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Services.UnitFilterService;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class FilterUnitsStage : ISimpleSyncStage
|
||||
{
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using PARR.Core.Repositories.Interfaces.JobRepositories;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class LoadJobStage : ISimpleSyncStage
|
||||
{
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
using PARR.Domain.Common.Rabbit.Messages.TemplateMatching;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.TemplateMatcher.Services.Interfaces;
|
||||
using PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
namespace PARR.TemplateMatcher.Services.Implementations.SimpleSync;
|
||||
namespace PARR.TemplateMatcher.Services.SimpleSync;
|
||||
|
||||
internal class UpdateNamesStage : ISimpleSyncWriteStage
|
||||
{
|
||||
|
||||
@@ -35,27 +35,27 @@ namespace PARR.TemplateMatcher
|
||||
services.AddScoped<ITemplateMatcher, Services.Implementations.TemplateMatcher>();
|
||||
|
||||
// Simple pipeline: Read-этапы
|
||||
services.AddScoped<ISimpleSyncStage, Services.Implementations.SimpleSync.LoadJobStage>(); //1
|
||||
services.AddScoped<ISimpleSyncStage, Services.Implementations.SimpleSync.FilterUnitsStage>(); //2
|
||||
services.AddScoped<ISimpleSyncStage, Services.Implementations.SimpleSync.AnalyzeChangesStage>(); //3
|
||||
services.AddScoped<ISimpleSyncStage, LoadJobStage>(); //1
|
||||
services.AddScoped<ISimpleSyncStage, Services.SimpleSync.FilterUnitsStage>(); //2
|
||||
services.AddScoped<ISimpleSyncStage, AnalyzeChangesStage>(); //3
|
||||
|
||||
// Simple pipeline: Write-этапы
|
||||
services.AddScoped<ISimpleSyncWriteStage, Services.Implementations.SimpleSync.AllocateTemplatesStage>(); //4
|
||||
services.AddScoped<ISimpleSyncWriteStage, Services.Implementations.SimpleSync.UpdateNamesStage>(); //5
|
||||
services.AddScoped<ISimpleSyncWriteStage, Services.Implementations.SimpleSync.DeactivateTemplatesStage>(); //6
|
||||
services.AddScoped<ISimpleSyncWriteStage, AllocateTemplatesStage>(); //4
|
||||
services.AddScoped<ISimpleSyncWriteStage, UpdateNamesStage>(); //5
|
||||
services.AddScoped<ISimpleSyncWriteStage, Services.SimpleSync.DeactivateTemplatesStage>(); //6
|
||||
|
||||
services.AddScoped<ITemplateSynchronizer, SimpleTemplateSynchronizer>();
|
||||
|
||||
// Grouped pipeline: Read-этапы
|
||||
services.AddScoped<IGroupedSyncStage, Services.Implementations.GroupedSync.LoadJobGroupStage>(); //1
|
||||
services.AddScoped<IGroupedSyncStage, Services.Implementations.GroupedSync.FilterUnitsStage>(); //2
|
||||
services.AddScoped<IGroupedSyncStage, Services.Implementations.GroupedSync.GroupFilterStage>(); //3
|
||||
services.AddScoped<IGroupedSyncStage, Services.Implementations.GroupedSync.ResolveConflictsStage>(); //4
|
||||
services.AddScoped<IGroupedSyncStage, Services.Implementations.GroupedSync.BuildGroupsStage>(); //5
|
||||
services.AddScoped<IGroupedSyncStage, LoadJobGroupStage>(); //1
|
||||
services.AddScoped<IGroupedSyncStage, Services.GroupedSync.FilterUnitsStage>(); //2
|
||||
services.AddScoped<IGroupedSyncStage, GroupFilterStage>(); //3
|
||||
services.AddScoped<IGroupedSyncStage, ResolveConflictsStage>(); //4
|
||||
services.AddScoped<IGroupedSyncStage, BuildGroupsStage>(); //5
|
||||
|
||||
// Grouped pipeline: Write-этапы
|
||||
services.AddScoped<IGroupedSyncWriteStage, Services.Implementations.GroupedSync.ProcessGroupsStage>(); //6
|
||||
services.AddScoped<IGroupedSyncWriteStage, Services.Implementations.GroupedSync.DeactivateTemplatesStage>();//7
|
||||
services.AddScoped<IGroupedSyncWriteStage, ProcessGroupsStage>(); //6
|
||||
services.AddScoped<IGroupedSyncWriteStage, Services.GroupedSync.DeactivateTemplatesStage>();//7
|
||||
|
||||
services.AddScoped<ITemplateSynchronizer, GroupedTemplateSynchronizer>();
|
||||
|
||||
@@ -81,6 +81,8 @@ namespace PARR.TemplateMatcher
|
||||
|
||||
//Сервис для неактуальных шаблонов
|
||||
services.AddScoped<IUnusedTemplatesSyncService, UnusedTemplatesSyncService>();
|
||||
services.AddTransient<IUnusedTemplateMessageFactory, UnusedTemplateMessageFactory>();
|
||||
services.AddScoped<IUnusedTemplateTargetUnitResolver, UnusedTemplateTargetUnitResolver>();
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddTemplateMatcherConfigurations(this IConfigurationBuilder builder, IServiceCollection services)
|
||||
|
||||
@@ -25,4 +25,8 @@
|
||||
<ProjectReference Include="..\PARR.TemplateDistributor\PARR.TemplateDistributor.csproj" />
|
||||
<ProjectReference Include="..\PARR.TemplateMatcher\PARR.TemplateMatcher.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="log\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using PARR.Core.Common.Interfaces;
|
||||
using PARR.Core.Repositories.Interfaces.JobGroupRepositories;
|
||||
using PARR.Core.Repositories.Interfaces.JobRepositories;
|
||||
using PARR.Domain.Entities.Base.History;
|
||||
using PARR.Domain.Entities.JobEntities;
|
||||
using PARR.Domain.Enums;
|
||||
using PARR.EsppApi;
|
||||
using PARR.EsppApi.Constants;
|
||||
@@ -43,12 +41,19 @@ namespace PARR.Test
|
||||
//var bbb = aaa.ToOffset(new TimeSpan(3, 0, 0));
|
||||
|
||||
|
||||
await TemplateMatcherTest();
|
||||
//await TemplateMatcherTest();
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
//var unitFilterService = scope.ServiceProvider.GetRequiredService<IUnitFilterService>();
|
||||
|
||||
//var t = await unitFilterService.GetRelatedUnitNamesAsync(Guid.Parse("4c35d6c3-f07d-4910-98af-b88247d22247"), Guid.Parse("4d4a1503-3a56-4e2a-bf92-a615c91c14ef"));
|
||||
|
||||
//t.ForEach(unit =>
|
||||
//{
|
||||
// _logger.LogInformation(unit);
|
||||
//});
|
||||
|
||||
//await NextRunTest();
|
||||
|
||||
//await GroupedSyncTest();
|
||||
await SimpleSyncTest();
|
||||
|
||||
#region test
|
||||
//using (var scope = serviceProvider.CreateScope())
|
||||
@@ -164,7 +169,6 @@ namespace PARR.Test
|
||||
|
||||
}
|
||||
#region SimpleSyncTest
|
||||
|
||||
private async Task SimpleSyncTest()
|
||||
{
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
@@ -182,7 +186,7 @@ namespace PARR.Test
|
||||
{
|
||||
//Guid.Parse("cfb0d2dd-192a-4ed5-a29c-25f0abf61895"),//11010
|
||||
//Guid.Parse("79976eaf-be7b-42a0-a4e3-a89d7f68a18e"),//17
|
||||
Guid.Parse("055ac0cc-10f7-4f96-baf6-9c8145b1332a")//318
|
||||
Guid.Parse("edcabe55-7f89-45ae-b946-d136b8594c53")//48
|
||||
};
|
||||
|
||||
if (!jobIds.Any())
|
||||
@@ -207,7 +211,8 @@ namespace PARR.Test
|
||||
InitiatorIp = "127.0.0.1",
|
||||
InitiatorParrComponentId = ParrComponentsEnum.Master,
|
||||
InitiatorComment = "Тестовая синхронизация SimpleTemplateSynchronizer"
|
||||
});
|
||||
}, dryRun: false
|
||||
);
|
||||
|
||||
sw.Stop();
|
||||
passed++;
|
||||
@@ -236,7 +241,7 @@ namespace PARR.Test
|
||||
var templateMatcher = scope.ServiceProvider.GetRequiredService<ITemplateMatcher>();
|
||||
var groupRepository = scope.ServiceProvider.GetRequiredService<IJobGroupRepository>();
|
||||
|
||||
await templateMatcher.SyncTemplatesForJob(Guid.Parse("055ac0cc-10f7-4f96-baf6-9c8145b1332a"),
|
||||
await templateMatcher.SyncTemplatesForJobGroup(Guid.Parse("9ed70f1e-69f6-4559-9139-b4947cce8d54"),
|
||||
new HistoryInitiator
|
||||
{
|
||||
InitiatorIp = "10.99.246.156",
|
||||
@@ -267,6 +272,56 @@ namespace PARR.Test
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
#region GroupedSyncTest
|
||||
private async Task GroupedSyncTest()
|
||||
{
|
||||
_logger.LogInformation("=== DryRun-тестирование GroupedTemplateSynchronizer ===");
|
||||
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
|
||||
var synchronizers = scope.ServiceProvider.GetRequiredService<IEnumerable<ITemplateSynchronizer>>();
|
||||
var groupedSync = synchronizers.FirstOrDefault(s => s is GroupedTemplateSynchronizer);
|
||||
|
||||
if (groupedSync == null)
|
||||
{
|
||||
_logger.LogError("[FAIL] GroupedTemplateSynchronizer не найден в DI");
|
||||
return;
|
||||
}
|
||||
|
||||
// Подставьте ID нужных JobGroup для тестирования
|
||||
var jobGroupIds = new List<Guid>
|
||||
{
|
||||
Guid.Parse("fb8678d0-aa8b-457d-8ea8-6452040c0692"), // Анализ производительности БД
|
||||
// Добавьте другие ID для проверки
|
||||
};
|
||||
|
||||
foreach (var jobGroupId in jobGroupIds)
|
||||
{
|
||||
_logger.LogInformation("--- DryRun: JobGroup {JobGroupId} ---", jobGroupId);
|
||||
|
||||
try
|
||||
{
|
||||
await groupedSync.SyncTemplatesForJobGroupAsync(
|
||||
jobGroupId,
|
||||
new HistoryInitiator
|
||||
{
|
||||
InitiatorIp = "127.0.0.1",
|
||||
InitiatorParrComponentId = ParrComponentsEnum.Master,
|
||||
InitiatorComment = "DryRun-тест"
|
||||
},
|
||||
dryRun: true // Ключевой флаг
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "[FAIL] DryRun для JobGroup {JobGroupId}", jobGroupId);
|
||||
}
|
||||
|
||||
_logger.LogInformation("--- DryRun завершён ---");
|
||||
_logger.LogInformation("");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private async Task NextRunTest()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user