feat(templateMatcher,dal): небольшой рефакторинг и добавлено журналирование промежуточных данных

This commit is contained in:
Mikhail Kuznetsov
2025-11-12 11:24:07 +10:00
parent 2950d21a69
commit 334595e81c
5 changed files with 111 additions and 46 deletions

View File

@@ -5,6 +5,7 @@ using PARR.DAL.Models.Job;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job; using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit; using PARR.DAL.Services.Interfaces.Unit;
using System.Net.NetworkInformation;
namespace PARR.DAL.DomainServices.Implementations namespace PARR.DAL.DomainServices.Implementations
@@ -51,7 +52,11 @@ namespace PARR.DAL.DomainServices.Implementations
public async Task<IEnumerable<Guid>?> GetUnitsIdByJobFilterAsync(Job job, int? takeCount = null) public async Task<IEnumerable<Guid>?> GetUnitsIdByJobFilterAsync(Job job, int? takeCount = null)
{ {
var result = new List<Guid>(); if (job.UnitFilters == null || !job.UnitFilters.Any())
{
logger.LogWarning("JobId={JobId} не содержит UnitFilters - пропускаем фильтрацию", job.Id);
return Array.Empty<Guid>();
}
var baseQuery = unitService var baseQuery = unitService
.Get().AsNoTracking() .Get().AsNoTracking()
@@ -76,16 +81,41 @@ namespace PARR.DAL.DomainServices.Implementations
.ThenInclude(t => t.UnitValues) .ThenInclude(t => t.UnitValues)
.ThenInclude(t => t.Value); .ThenInclude(t => t.Value);
var result = new List<Guid>();
var filterIndex = 0;
foreach (var unitFilter in job.UnitFilters) foreach (var unitFilter in job.UnitFilters)
{ {
if (takeCount.HasValue && result.Count() > takeCount.Value) filterIndex++;
break;
if (takeCount.HasValue && result.Count >= takeCount.Value)
{
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)); var query = baseQuery.Where(t => EF.Functions.ILike(t.Name, unitFilter.UnitFilter));
//фильтруем по полям
foreach (var fieldFilter in unitFilter.FieldFilters) 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)))); {
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()) if (unitFilter.RelationshipFilters.Any())
{ {
var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList(); var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList();
@@ -94,35 +124,70 @@ namespace PARR.DAL.DomainServices.Implementations
if (parentFilter.IsInverse == false) if (parentFilter.IsInverse == false)
{ {
if (parentFilter.IsFullMatch) 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))))); 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 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))))); 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 else
{ {
if (parentFilter.IsFullMatch) 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))))); 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 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))))); 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) if (job.isParentRelationships == true)
query = query.Where(t => t.ParentUnits.Count() >= job.MinValueRelationships && t.ParentUnits.Count() <= job.MaxValueRelationships); query = query.Where(t => t.ParentUnits.Count >= job.MinValueRelationships && t.ParentUnits.Count <= job.MaxValueRelationships);
else else
query = query.Where(t => t.ChildUnits.Count() >= job.MinValueRelationships && t.ChildUnits.Count() <= job.MaxValueRelationships); query = query.Where(t => t.ChildUnits.Count >= job.MinValueRelationships && t.ChildUnits.Count <= job.MaxValueRelationships);
} }
var newUnits = await query.Select(t => t.Id).ToListAsync(); var newUnits = await query
.Select(t => t.Id)
.Take(remainig)
.ToListAsync();
result.AddRange(newUnits); result.AddRange(newUnits);
logger.LogDebug("Фильтр {FilterIndex}: найдено {Count} Unit'ов (осталось набрать: {Remaining})",
filterIndex, newUnits.Count,Math.Max(0,takeCount.GetValueOrDefault(int.MaxValue)-result.Count));
}
catch (Exception ex)
{
logger.LogError(ex, "Ошибка применения UnitFilter {FilterIndex} для JobId={JobId}", filterIndex, job.Id);
continue;
}
} }
if (takeCount.HasValue && result.Count() > takeCount.Value) if (takeCount.HasValue && result.Count > takeCount.Value)
result = result.Take(takeCount.Value).ToList(); result = result.Take(takeCount.Value).ToList();
logger.LogInformation("JobId={JobId}: обработано {FilterCount} фильтров, найдено {UnitCount} Unit'ов", job.Id, job.UnitFilters.Count, result.Count);
return result; return result;
} }

View File

@@ -9,14 +9,14 @@ namespace PARR.TemplateMatcher
{ {
internal class MqTemplateMatcher : IMqTemplateMatcher internal class MqTemplateMatcher : IMqTemplateMatcher
{ {
private readonly ILogger<IMqTemplateMatcher> logger; private readonly ILogger<MqTemplateMatcher> logger;
private readonly MqSettings mqSettings; private readonly MqSettings mqSettings;
private readonly IMqService mqService; private readonly IMqService mqService;
private readonly ITransformService transformService; private readonly ITransformService transformService;
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;
public MqTemplateMatcher( public MqTemplateMatcher(
ILogger<IMqTemplateMatcher> logger, ILogger<MqTemplateMatcher> logger,
MqSettings mqSettings, MqSettings mqSettings,
IMqService mqService, IMqService mqService,
ITransformService transformService, ITransformService transformService,

View File

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace PARR.TemplateMatcher.Settings namespace PARR.TemplateMatcher.Settings
{ {
public class MqSettings internal class MqSettings
{ {
public TemplateMatcher TemplateMatcher { get; set; } = new TemplateMatcher(); public TemplateMatcher TemplateMatcher { get; set; } = new TemplateMatcher();
public TemplateGenerator TemplateGenerator { get; set; } = new TemplateGenerator(); public TemplateGenerator TemplateGenerator { get; set; } = new TemplateGenerator();

View File

@@ -9,15 +9,15 @@ using System.Text.Json;
namespace PARR.TemplateMatcher namespace PARR.TemplateMatcher
{ {
public class TemplateMatcher : ITemplateMatcher internal class TemplateMatcher : ITemplateMatcher
{ {
private readonly Logger<TemplateMatcher> logger; private readonly ILogger<TemplateMatcher> logger;
private readonly IUnitFilterService unitFilterService; private readonly IUnitFilterService unitFilterService;
private readonly MqSettings mqSettings; private readonly MqSettings mqSettings;
private readonly IMqService mqService; private readonly IMqService mqService;
public TemplateMatcher( public TemplateMatcher(
Logger<TemplateMatcher> logger, ILogger<TemplateMatcher> logger,
IUnitFilterService unitFilterService, IUnitFilterService unitFilterService,
MqSettings mqSettings, MqSettings mqSettings,
IMqService mqService IMqService mqService
@@ -46,7 +46,7 @@ namespace PARR.TemplateMatcher
var msg = JsonSerializer.Serialize(mqRequest); 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) if (result.IsSuccess)
logger.LogInformation($"Отправлен запрос на создание шаблона: {msg}"); logger.LogInformation($"Отправлен запрос на создание шаблона: {msg}");

View File

@@ -4,27 +4,27 @@ namespace PARR.TemplateMatcherWorker
{ {
public class Worker : BackgroundService public class Worker : BackgroundService
{ {
private readonly ILogger<Worker> logger; private readonly ILogger<Worker> _logger;
private readonly IMqTemplateMatcher mqTemplateTaskGenerator; private readonly IMqTemplateMatcher mqTemplateMatcher;
public Worker( public Worker(
ILogger<Worker> logger, ILogger<Worker> logger,
IMqTemplateMatcher mqTemplateTaskGenerator IMqTemplateMatcher mqTemplateMatcher
) )
{ {
logger = logger; _logger = logger;
this.mqTemplateTaskGenerator = mqTemplateTaskGenerator; this.mqTemplateMatcher = mqTemplateMatcher;
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await mqTemplateTaskGenerator.StartAsync(); await mqTemplateMatcher.StartAsync();
} }
public override Task StopAsync(CancellationToken cancellationToken) public override Task StopAsync(CancellationToken cancellationToken)
{ {
mqTemplateTaskGenerator.StopAsync().Wait(); mqTemplateMatcher.StopAsync().Wait();
return base.StopAsync(cancellationToken); return base.StopAsync(cancellationToken);
} }