diff --git a/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs b/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs index b062e3cf..05b630c5 100644 --- a/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs +++ b/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs @@ -5,6 +5,7 @@ using PARR.DAL.Models.Job; using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces.Job; using PARR.DAL.Services.Interfaces.Unit; +using System.Net.NetworkInformation; namespace PARR.DAL.DomainServices.Implementations @@ -51,7 +52,11 @@ namespace PARR.DAL.DomainServices.Implementations public async Task?> GetUnitsIdByJobFilterAsync(Job job, int? takeCount = null) { - var result = new List(); + if (job.UnitFilters == null || !job.UnitFilters.Any()) + { + logger.LogWarning("JobId={JobId} не содержит UnitFilters - пропускаем фильтрацию", job.Id); + return Array.Empty(); + } var baseQuery = unitService .Get().AsNoTracking() @@ -76,53 +81,113 @@ namespace PARR.DAL.DomainServices.Implementations .ThenInclude(t => t.UnitValues) .ThenInclude(t => t.Value); + var result = new List(); + var filterIndex = 0; + foreach (var unitFilter in job.UnitFilters) { - if (takeCount.HasValue && result.Count() > takeCount.Value) - break; + filterIndex++; - var query = baseQuery.Where(t => EF.Functions.ILike(t.Name, unitFilter.UnitFilter)); - - foreach (var fieldFilter in unitFilter.FieldFilters) - query = query.Where(t => t.UnitValues.Any(x => x.FieldId == fieldFilter.FieldId && (x.Value!.Value != null && EF.Functions.ILike(x.Value!.Value, fieldFilter.ValueMask)))); - - if (unitFilter.RelationshipFilters.Any()) + if (takeCount.HasValue && result.Count >= takeCount.Value) { - var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList(); - foreach (var parentFilter in parentFilters) + logger.LogDebug("Достигнуто ограничение takeCount={TakeCount} после {FilterIndex} фильтров", takeCount.Value, filterIndex - 1); + break; + } + + var remainig = takeCount.HasValue ? takeCount.Value - result.Count : int.MaxValue; + if (remainig <= 0) break; + + try + { + //фильтруем по имени + var query = baseQuery.Where(t => EF.Functions.ILike(t.Name, unitFilter.UnitFilter)); + + //фильтруем по полям + foreach (var fieldFilter in unitFilter.FieldFilters) { - if (parentFilter.IsInverse == false) + var fieldId = fieldFilter.FieldId; + var fieldValueMask = fieldFilter.ValueMask; + query = query.Where(t => + t.UnitValues.Any(x => + x.FieldId == fieldId && + x.Value != null && + x.Value.Value != null && + EF.Functions.ILike(x.Value.Value, fieldValueMask))); + } + + //фильтруем по значениям в связях + if (unitFilter.RelationshipFilters.Any()) + { + var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList(); + foreach (var parentFilter in parentFilters) { - if (parentFilter.IsFullMatch) - query = query.Where(t => !t.ParentUnits.Any() || t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask))))); + if (parentFilter.IsInverse == false) + { + if (parentFilter.IsFullMatch) + query = query.Where(t => !t.ParentUnits.Any() || + t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => + pf.FieldId == parentFilter.FieldId && + pf.Value !=null && + pf.Value.Value != null && + EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))); + else + query = query.Where(t => !t.ParentUnits.Any() || + t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => + pf.FieldId == parentFilter.FieldId && + pf.Value !=null && + pf.Value!.Value != null && + EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))); + } else - query = query.Where(t => !t.ParentUnits.Any() || t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask))))); - } - else - { - if (parentFilter.IsFullMatch) - query = query.Where(t => !t.ParentUnits.Any() || !t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask))))); - else - query = query.Where(t => !t.ParentUnits.Any() || !t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => pf.FieldId == parentFilter.FieldId && (pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask))))); + { + if (parentFilter.IsFullMatch) + query = query.Where(t => !t.ParentUnits.Any() || + !t.ParentUnits.All(p => p.ParentUnit!.UnitValues.Any(pf => + pf.FieldId == parentFilter.FieldId && + pf.Value !=null && + pf.Value!.Value != null && + EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))); + else + query = query.Where(t => !t.ParentUnits.Any() || + !t.ParentUnits.Any(p => p.ParentUnit!.UnitValues.Any(pf => + pf.FieldId == parentFilter.FieldId && + pf.Value != null && + pf.Value!.Value != null && EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))); + } } } - } - if (job.Group?.IsUmbrella == true) + //фильтруем по количеству связей + if (job.Group?.IsUmbrella == true) + { + if (job.isParentRelationships == true) + query = query.Where(t => t.ParentUnits.Count >= job.MinValueRelationships && t.ParentUnits.Count <= job.MaxValueRelationships); + else + query = query.Where(t => t.ChildUnits.Count >= job.MinValueRelationships && t.ChildUnits.Count <= job.MaxValueRelationships); + } + + var newUnits = await query + .Select(t => t.Id) + .Take(remainig) + .ToListAsync(); + + result.AddRange(newUnits); + + logger.LogDebug("Фильтр {FilterIndex}: найдено {Count} Unit'ов (осталось набрать: {Remaining})", + filterIndex, newUnits.Count,Math.Max(0,takeCount.GetValueOrDefault(int.MaxValue)-result.Count)); + } + catch (Exception ex) { - if (job.isParentRelationships == true) - query = query.Where(t => t.ParentUnits.Count() >= job.MinValueRelationships && t.ParentUnits.Count() <= job.MaxValueRelationships); - else - query = query.Where(t => t.ChildUnits.Count() >= job.MinValueRelationships && t.ChildUnits.Count() <= job.MaxValueRelationships); + logger.LogError(ex, "Ошибка применения UnitFilter {FilterIndex} для JobId={JobId}", filterIndex, job.Id); + continue; } - - var newUnits = await query.Select(t => t.Id).ToListAsync(); - result.AddRange(newUnits); } - if (takeCount.HasValue && result.Count() > takeCount.Value) + if (takeCount.HasValue && result.Count > takeCount.Value) result = result.Take(takeCount.Value).ToList(); + logger.LogInformation("JobId={JobId}: обработано {FilterCount} фильтров, найдено {UnitCount} Unit'ов", job.Id, job.UnitFilters.Count, result.Count); + return result; } diff --git a/PARR.TemplateMatcher/MqTemplateMatcher.cs b/PARR.TemplateMatcher/MqTemplateMatcher.cs index 5513e2bc..2c6af24f 100644 --- a/PARR.TemplateMatcher/MqTemplateMatcher.cs +++ b/PARR.TemplateMatcher/MqTemplateMatcher.cs @@ -9,14 +9,14 @@ namespace PARR.TemplateMatcher { internal class MqTemplateMatcher : IMqTemplateMatcher { - private readonly ILogger logger; + private readonly ILogger logger; private readonly MqSettings mqSettings; private readonly IMqService mqService; private readonly ITransformService transformService; private readonly IServiceProvider serviceProvider; public MqTemplateMatcher( - ILogger logger, + ILogger logger, MqSettings mqSettings, IMqService mqService, ITransformService transformService, diff --git a/PARR.TemplateMatcher/Settings/MqSettings.cs b/PARR.TemplateMatcher/Settings/MqSettings.cs index a9485785..ee880631 100644 --- a/PARR.TemplateMatcher/Settings/MqSettings.cs +++ b/PARR.TemplateMatcher/Settings/MqSettings.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace PARR.TemplateMatcher.Settings { - public class MqSettings + internal class MqSettings { public TemplateMatcher TemplateMatcher { get; set; } = new TemplateMatcher(); public TemplateGenerator TemplateGenerator { get; set; } = new TemplateGenerator(); diff --git a/PARR.TemplateMatcher/TemplateMatcher.cs b/PARR.TemplateMatcher/TemplateMatcher.cs index 7c109ebf..6cd17ff3 100644 --- a/PARR.TemplateMatcher/TemplateMatcher.cs +++ b/PARR.TemplateMatcher/TemplateMatcher.cs @@ -9,15 +9,15 @@ using System.Text.Json; namespace PARR.TemplateMatcher { - public class TemplateMatcher : ITemplateMatcher + internal class TemplateMatcher : ITemplateMatcher { - private readonly Logger logger; + private readonly ILogger logger; private readonly IUnitFilterService unitFilterService; private readonly MqSettings mqSettings; private readonly IMqService mqService; public TemplateMatcher( - Logger logger, + ILogger logger, IUnitFilterService unitFilterService, MqSettings mqSettings, IMqService mqService @@ -46,7 +46,7 @@ namespace PARR.TemplateMatcher var msg = JsonSerializer.Serialize(mqRequest); - var result = await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg }); + var result = new MqSendResult { IsSuccess = true };//TODO await mqService.SendAsync(mqSettings.TemplateGenerator, new[] { msg }); if (result.IsSuccess) logger.LogInformation($"Отправлен запрос на создание шаблона: {msg}"); diff --git a/PARR.TemplateMatcherWorker/Worker.cs b/PARR.TemplateMatcherWorker/Worker.cs index f64af81f..ab60a6fc 100644 --- a/PARR.TemplateMatcherWorker/Worker.cs +++ b/PARR.TemplateMatcherWorker/Worker.cs @@ -4,27 +4,27 @@ namespace PARR.TemplateMatcherWorker { public class Worker : BackgroundService { - private readonly ILogger logger; - private readonly IMqTemplateMatcher mqTemplateTaskGenerator; + private readonly ILogger _logger; + private readonly IMqTemplateMatcher mqTemplateMatcher; public Worker( ILogger logger, - IMqTemplateMatcher mqTemplateTaskGenerator + IMqTemplateMatcher mqTemplateMatcher ) { - logger = logger; - this.mqTemplateTaskGenerator = mqTemplateTaskGenerator; + _logger = logger; + this.mqTemplateMatcher = mqTemplateMatcher; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - await mqTemplateTaskGenerator.StartAsync(); + await mqTemplateMatcher.StartAsync(); } public override Task StopAsync(CancellationToken cancellationToken) { - mqTemplateTaskGenerator.StopAsync().Wait(); + mqTemplateMatcher.StopAsync().Wait(); return base.StopAsync(cancellationToken); }