From d90924bfa2bca201e990fcad98c71da56ab395b3 Mon Sep 17 00:00:00 2001 From: Mikhail Kuznetsov Date: Thu, 20 Nov 2025 11:37:44 +1000 Subject: [PATCH] =?UTF-8?q?feat(templateMatcher,dal):=20=D0=BD=D0=B5=D0=B1?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B9=20=D1=80=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3,=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20Dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.AIHITSyncerWorker/Worker.cs | 39 +-- .../V1/JobUnitPreviewController.cs | 9 + .../Implementations/UnitFilterService.cs | 311 +++++++++++------- .../Interfaces/IUnitFilterService.cs | 29 +- PARR.TemplateMatcher/TemplateMatcher.cs | 2 +- PARR.TemplateMatcherWorker/Dockerfile | 34 ++ .../PARR.TemplateMatcherWorker.csproj | 2 + .../Properties/launchSettings.json | 11 +- .../TemplateTaskGenerator.cs | 2 +- 9 files changed, 273 insertions(+), 166 deletions(-) create mode 100644 PARR.TemplateMatcherWorker/Dockerfile diff --git a/PARR.AIHITSyncerWorker/Worker.cs b/PARR.AIHITSyncerWorker/Worker.cs index bb40dc0d..b779b682 100644 --- a/PARR.AIHITSyncerWorker/Worker.cs +++ b/PARR.AIHITSyncerWorker/Worker.cs @@ -1,4 +1,4 @@ -using PARR.AIHITMainSyncer; +using PARR.AIHITMainSyncer; namespace PARR.AIHITSyncerWorker { @@ -16,47 +16,14 @@ namespace PARR.AIHITSyncerWorker protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - //await aihitSyncer.StartAsync(); - //await Task.Delay(Timeout.Infinite, stoppingToken); - while (!stoppingToken.IsCancellationRequested) - { - try - { - await aihitSyncer.StartAsync(); - await Task.Delay(Timeout.Infinite, stoppingToken); - // StartAsync ( ), - // , , Task.Delay break. - // StartAsync , - // , ** ** . - // , . - _logger.LogWarning("AihitMainSyncer . 10 ..."); - } - catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) - { - // - break; - } - catch (Exception ex) - { - _logger.LogError(ex, " Worker. 10 ..."); - } - - try - { - await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); - } - catch (OperationCanceledException) - { - break; - } - } + await aihitSyncer.StartAsync(); + await Task.Delay(Timeout.Infinite, stoppingToken); } public override Task StopAsync(CancellationToken cancellationToken) { aihitSyncer.StopAsync(); - return base.StopAsync(cancellationToken); } } diff --git a/PARR.API/Controllers/V1/JobUnitPreviewController.cs b/PARR.API/Controllers/V1/JobUnitPreviewController.cs index d1ff51ef..3a6debd5 100644 --- a/PARR.API/Controllers/V1/JobUnitPreviewController.cs +++ b/PARR.API/Controllers/V1/JobUnitPreviewController.cs @@ -11,6 +11,7 @@ using PARR.API.Controllers.V1.Base; using PARR.Constants; using PARR.DAL.DomainServices.Interfaces; using PARR.DAL.Models.Job; +using PARR.DAL.Services.Interfaces.Job; using PARR.DAL.Services.Interfaces.Unit; using static PARR.API.Contracts.V1.ApiRoutes; using Job = PARR.DAL.Models.Job.Job; @@ -27,6 +28,7 @@ namespace PARR.API.Controllers.V1 private readonly IUnitFilterService unitFilterService; private readonly IValidator jobValidator; private readonly IUnitService unitService; + private readonly IJobGroupService jobGroupService; private readonly IMapper mapper; public JobUnitPreviewController( @@ -34,6 +36,7 @@ namespace PARR.API.Controllers.V1 IUnitFilterService unitFilterService, IValidator jobValidator, IUnitService unitService, + IJobGroupService jobGroupService, IMapper mapper ) { @@ -41,6 +44,7 @@ namespace PARR.API.Controllers.V1 this.unitFilterService = unitFilterService; this.jobValidator = jobValidator; this.unitService = unitService; + this.jobGroupService = jobGroupService; this.mapper = mapper; } @@ -61,6 +65,11 @@ namespace PARR.API.Controllers.V1 var job = mapper.Map(request); + var jobGroup = await jobGroupService.Get().AsNoTracking() + .Include(t=>t.GroupType) + .FirstAsync(t=>t.Id == job.GroupId); + job.Group = jobGroup; + var unitIds = await unitFilterService.GetUnitsIdByJobFilterAsync(job, 100); if (unitIds == null || !unitIds.Any()) diff --git a/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs b/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs index 8ffeaff5..34086b15 100644 --- a/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs +++ b/PARR.DAL/DomainServices/Implementations/UnitFilterService.cs @@ -1,11 +1,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using PARR.DAL.Contracts; using PARR.DAL.DomainServices.Interfaces; 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; +using System.Text.RegularExpressions; namespace PARR.DAL.DomainServices.Implementations @@ -33,7 +35,6 @@ namespace PARR.DAL.DomainServices.Implementations public async Task?> GetUnitsIdByJobFilterAsync(Guid jobId, int? takeCount = null) { - var job = await jobService .Get().AsNoTracking() .Include(t => t.UnitFilters) @@ -41,6 +42,7 @@ namespace PARR.DAL.DomainServices.Implementations .Include(t => t.UnitFilters) .ThenInclude(t => t.RelationshipFilters) .Include(t => t.Group) + .ThenInclude(t => t.GroupType) .FirstOrDefaultAsync(t => t.Id == jobId); if (job == null) @@ -52,171 +54,258 @@ namespace PARR.DAL.DomainServices.Implementations public async Task?> GetUnitsIdByJobFilterAsync(Job job, int? takeCount = null) { + #region проверка инклудов + if (job.Group == null) + { + logger.LogWarning("JobId={JobId} не содержит Group - пропускаем фильтрацию", job.Id); + throw new ArgumentNullException(nameof(Group)); + } + + if (job.Group.GroupType == null) + { + logger.LogWarning("JobId={JobId} не содержит GroupType - пропускаем фильтрацию", job.Id); + throw new ArgumentNullException(nameof(JobGroupType)); + } + if (job.UnitFilters == null || !job.UnitFilters.Any()) { logger.LogWarning("JobId={JobId} не содержит UnitFilters - пропускаем фильтрацию", job.Id); - return Array.Empty(); + throw new ArgumentNullException(nameof(JobUnitFilter)); } + #endregion - var baseQuery = unitService - .Get().AsNoTracking() - .Include(t => t.UnitValues) - .ThenInclude(t => t.Field) - .Include(t => t.UnitValues) - .ThenInclude(t => t.Value) - .Include(t => t.ParentUnits) - .ThenInclude(t => t.ParentUnit) - .ThenInclude(t => t.UnitValues) - .ThenInclude(t => t.Field) - .Include(t => t.ParentUnits) - .ThenInclude(t => t.ParentUnit) - .ThenInclude(t => t.UnitValues) - .ThenInclude(t => t.Value) - .Include(t => t.ChildUnits) - .ThenInclude(t => t.ChildUnit) - .ThenInclude(t => t.UnitValues) - .ThenInclude(t => t.Field) - .Include(t => t.ChildUnits) - .ThenInclude(t => t.ChildUnit) - .ThenInclude(t => t.UnitValues) - .ThenInclude(t => t.Value); + var maxCount = takeCount ?? int.MaxValue; + var collectedIds = new HashSet(); // ← гарантирует уникальность + var filterNumber = 0; - var result = new List(); - var filterIndex = 0; - - foreach (var unitFilter in job.UnitFilters) + foreach (var filter in job.UnitFilters) { - filterIndex++; + filterNumber++; - if (takeCount.HasValue && result.Count >= takeCount.Value) + // Прекращаем, если набрали достаточно + if (collectedIds.Count >= maxCount) { - logger.LogDebug("Достигнуто ограничение takeCount={TakeCount} после {FilterIndex} фильтров", takeCount.Value, filterIndex - 1); + logger.LogDebug("Достигнут лимит takeCount={TakeCount} после {FilterCount} фильтров", maxCount, filterNumber - 1); break; } - var remainig = takeCount.HasValue ? takeCount.Value - result.Count : int.MaxValue; - if (remainig <= 0) break; + var remaining = maxCount - collectedIds.Count; + if (remaining <= 0) break; try { - //фильтруем по имени - var query = baseQuery.Where(t => EF.Functions.ILike(t.Name, unitFilter.UnitFilter)); + // Стартуем с базового условия — имя Unit'а + var query = unitService.Get().AsNoTracking() + .Where(unit => EF.Functions.ILike(unit.Name, filter.UnitFilter)); - //фильтруем по полям - foreach (var fieldFilter in unitFilter.FieldFilters) + // 1. Фильтры по полям (UnitValues) + foreach (var fieldFilter in filter.FieldFilters) { 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))); + var valueMask = fieldFilter.ValueMask; + + query = query.Where(unit => + unit.UnitValues.Any(value => + value.FieldId == fieldId + && value.Value != null + && value.Value.Value != null + && EF.Functions.ILike(value.Value.Value, valueMask))); } - - //фильтруем по значениям в связях - if (unitFilter.RelationshipFilters.Any()) + + // 2. Фильтры по связям (родителям и детям) + foreach (var relFilter in filter.RelationshipFilters) { - var parentFilters = unitFilter.RelationshipFilters.Where(t => t.IsParent == true).ToList(); - foreach (var parentFilter in parentFilters) + var fieldId = relFilter.FieldId; + var valueMask = relFilter.ValueMask; + + if (relFilter.IsParent) { - if (parentFilter.IsInverse == false) + // Работаем с ParentUnits → pu.ParentUnit + if (relFilter.IsInverse) { - 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)))); + // "Обратный фильтр": ищем Unit'ы, у которых связанные Unit'ы НЕ имеют указанного значения + if (relFilter.IsFullMatch) + { + // Все родители НЕ должны иметь такое значение + query = query.Where(unit => + !unit.ParentUnits.Any() || // если связей нет — подходит + unit.ParentUnits.All(parentLink => + !parentLink.ParentUnit!.UnitValues.Any(parentValue => + parentValue.FieldId == fieldId + && parentValue.Value != null + && parentValue.Value.Value != null + && EF.Functions.ILike(parentValue.Value.Value, 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)))); + { + // Хотя бы один родитель НЕ имеет такого значения + query = query.Where(unit => + !unit.ParentUnits.Any() || + unit.ParentUnits.Any(parentLink => + !parentLink.ParentUnit!.UnitValues.Any(parentValue => + parentValue.FieldId == fieldId + && parentValue.Value != null + && parentValue.Value.Value != null + && EF.Functions.ILike(parentValue.Value.Value, 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 !=null && - pf.Value!.Value != null && - EF.Functions.ILike(pf.Value.Value, parentFilter.ValueMask)))); + // Прямой фильтр: связанные Unit'ы ДОЛЖНЫ иметь значение + if (relFilter.IsFullMatch) + { + // Все родители должны иметь такое значение + query = query.Where(unit => + !unit.ParentUnits.Any() || + unit.ParentUnits.All(parentLink => + parentLink.ParentUnit!.UnitValues.Any(parentValue => + parentValue.FieldId == fieldId + && parentValue.Value != null + && parentValue.Value.Value != null + && EF.Functions.ILike(parentValue.Value.Value, 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)))); + { + // Хотя бы один родитель должен иметь такое значение + query = query.Where(unit => + unit.ParentUnits.Any(parentLink => + parentLink.ParentUnit!.UnitValues.Any(parentValue => + parentValue.FieldId == fieldId + && parentValue.Value != null + && parentValue.Value.Value != null + && EF.Functions.ILike(parentValue.Value.Value, valueMask)))); + } + } + } + else + { + // relFilter.IsParent == false → работаем с детьми (ChildUnits) + if (relFilter.IsInverse) + { + if (relFilter.IsFullMatch) + { + query = query.Where(unit => + !unit.ChildUnits.Any() || + unit.ChildUnits.All(childLink => + !childLink.ChildUnit!.UnitValues.Any(childValue => + childValue.FieldId == fieldId + && childValue.Value != null + && childValue.Value.Value != null + && EF.Functions.ILike(childValue.Value.Value, valueMask)))); + } + else + { + query = query.Where(unit => + !unit.ChildUnits.Any() || + unit.ChildUnits.Any(childLink => + !childLink.ChildUnit!.UnitValues.Any(childValue => + childValue.FieldId == fieldId + && childValue.Value != null + && childValue.Value.Value != null + && EF.Functions.ILike(childValue.Value.Value, valueMask)))); + } + } + else + { + if (relFilter.IsFullMatch) + { + query = query.Where(unit => + !unit.ChildUnits.Any() || + unit.ChildUnits.All(childLink => + childLink.ChildUnit!.UnitValues.Any(childValue => + childValue.FieldId == fieldId + && childValue.Value != null + && childValue.Value.Value != null + && EF.Functions.ILike(childValue.Value.Value, valueMask)))); + } + else + { + query = query.Where(unit => + unit.ChildUnits.Any(childLink => + childLink.ChildUnit!.UnitValues.Any(childValue => + childValue.FieldId == fieldId + && childValue.Value != null + && childValue.Value.Value != null + && EF.Functions.ILike(childValue.Value.Value, valueMask)))); + } } } } - //фильтруем по количеству связей - if (job.Group?.IsUmbrella == true) + // 3. Ограничение по количеству связей (только для umbrella-групп) + if (job.Group.GroupType.Code == JobGroupTypesEnum.Umbrella) { + int min = job.MinValueRelationships.GetValueOrDefault(0); + int max = job.MaxValueRelationships.GetValueOrDefault(int.MaxValue); + if (job.IsParentRelationships == true) - query = query.Where(t => t.ParentUnits.Count >= job.MinValueRelationships && t.ParentUnits.Count <= job.MaxValueRelationships); + { + query = query.Where(unit => + unit.ParentUnits.Count >= min && unit.ParentUnits.Count <= max); + } else - query = query.Where(t => t.ChildUnits.Count >= job.MinValueRelationships && t.ChildUnits.Count <= job.MaxValueRelationships); + { + query = query.Where(unit => + unit.ChildUnits.Count >= min && unit.ChildUnits.Count <= max); + } } - var newUnits = await query - .Select(t => t.Id) - .Take(remainig) + // Запрашиваем в БД с учётом оставшегося лимита + var newIds = await query + .Select(unit => unit.Id) + .Take(remaining) .ToListAsync(); - result.AddRange(newUnits); + collectedIds.UnionWith(newIds); + + logger.LogDebug( + "Фильтр #{Index} (Id={FilterId}): найдено {Count} Unit'ов. Всего: {Total}", + filterNumber, filter.Id, newIds.Count, collectedIds.Count); - 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; + logger.LogError(ex, "Ошибка при обработке фильтра {FilterId} (#{Index}) для Job {JobId}", + filter.Id, filterNumber, job.Id); + // Продолжаем — другие фильтры могут сработать } } - 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); + var result = collectedIds.Take(maxCount).ToList(); + logger.LogInformation("Job {JobId}: из {FilterCount} фильтров получено {UnitCount} уникальных Unit'ов", + job.Id, job.UnitFilters.Count, result.Count); return result; } - - public async Task?> GetUnitsIdForExistTemplatesByJobFilterAsync(Guid jobId, int? takeCount = null) + public async Task> GetUnitsIdByJobFilterWithTemplateStatusAsync( + Guid jobId, + bool mustHaveTemplate, + int? takeCount = null + ) { - var unitIdsMustBeCreated = await GetUnitsIdByJobFilterAsync(jobId, takeCount); + var unitIds = await GetUnitsIdByJobFilterAsync(jobId, takeCount); + if (unitIds == null || !unitIds.Any()) + return Array.Empty(); - if (unitIdsMustBeCreated == null || !unitIdsMustBeCreated.Any()) - return null; + var unitIdSet = unitIds.ToHashSet(); - var unitWithTemplates = await templateService.Get().AsNoTracking().Where(t => t.JobId == jobId && unitIdsMustBeCreated.Any(x => x == t.UnitId)).Select(t => t.UnitId).ToListAsync(); + // Получаем UnitId, для которых уже есть шаблоны по этому jobId + var existingUnitIds = await templateService + .Get() + .AsNoTracking() + .Where(template => + template.JobId == jobId && + unitIdSet.Contains(template.UnitId)) + .Select(template => template.UnitId) + .ToListAsync(); - return unitWithTemplates; - } + var existingSet = existingUnitIds.ToHashSet(); - public async Task?> GetUnitsIdForNotExistTemplatesByJobFilterAsync(Guid jobId, int? takeCount = null) - { - var unitIdsMustBeCreated = await GetUnitsIdByJobFilterAsync(jobId, takeCount); - - if (unitIdsMustBeCreated == null || !unitIdsMustBeCreated.Any()) - return null; - - var unitIdsWithTemplate = await templateService.Get().AsNoTracking().Where(t => t.JobId == jobId).Select(t => t.UnitId).ToListAsync(); - - var unitsIdToCreateTemplate = unitIdsMustBeCreated.Where(t => !unitIdsWithTemplate.Any(x => x == t)); - - return unitsIdToCreateTemplate; + return mustHaveTemplate + ? existingSet + : unitIdSet.Except(existingSet); } } } diff --git a/PARR.DAL/DomainServices/Interfaces/IUnitFilterService.cs b/PARR.DAL/DomainServices/Interfaces/IUnitFilterService.cs index 049a23e0..4ddb00e1 100644 --- a/PARR.DAL/DomainServices/Interfaces/IUnitFilterService.cs +++ b/PARR.DAL/DomainServices/Interfaces/IUnitFilterService.cs @@ -5,28 +5,31 @@ namespace PARR.DAL.DomainServices.Interfaces public interface IUnitFilterService { /// - /// Получить все Unit.Id, для которых должны быть созданы Template + /// Получить все Unit.Id соответствующие настройкам фильтрации Job /// /// Id работы /// Task?> GetUnitsIdByJobFilterAsync(Guid jobId, int? takeCount = null); + + /// + /// Получить все Unit.Id соответствующие настройкам фильтрации Job + /// + /// Job обязательно должен содержать UnitFilter, Group и GroupType + /// Task?> GetUnitsIdByJobFilterAsync(Job job, int? takeCount = null); - /// - /// Получить все Unit.Id, для которых не были созданы Template - /// - /// Id работы - /// - Task?> GetUnitsIdForNotExistTemplatesByJobFilterAsync(Guid jobId, int? takeCount = null); /// - /// Получить все Unit.Id, для которых были созданы Template + /// Получить список Id ЭК в зависимости от параметра mustHaveTemplate /// - /// Id работы - /// - Task?> GetUnitsIdForExistTemplatesByJobFilterAsync(Guid jobId, int? takeCount = null); - - + /// + /// + /// true - ЭК, которые имеют связанные шаблоны + /// false - ЭК, для которых шаблоны не созданы + /// + /// + /// Лист Id ЭК + Task> GetUnitsIdByJobFilterWithTemplateStatusAsync(Guid jobId, bool mustHaveTemplate, int? takeCount = null); } } diff --git a/PARR.TemplateMatcher/TemplateMatcher.cs b/PARR.TemplateMatcher/TemplateMatcher.cs index 6cd17ff3..2b487c34 100644 --- a/PARR.TemplateMatcher/TemplateMatcher.cs +++ b/PARR.TemplateMatcher/TemplateMatcher.cs @@ -30,7 +30,7 @@ namespace PARR.TemplateMatcher } public async Task MatchTemplatesForJob(Guid jobId) { - var unitIdsToCreateTemplate = await unitFilterService.GetUnitsIdForNotExistTemplatesByJobFilterAsync(jobId); + var unitIdsToCreateTemplate = await unitFilterService.GetUnitsIdByJobFilterWithTemplateStatusAsync(jobId,false); if (unitIdsToCreateTemplate == null || !unitIdsToCreateTemplate.Any()) return; diff --git a/PARR.TemplateMatcherWorker/Dockerfile b/PARR.TemplateMatcherWorker/Dockerfile new file mode 100644 index 00000000..6920b10e --- /dev/null +++ b/PARR.TemplateMatcherWorker/Dockerfile @@ -0,0 +1,34 @@ +# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +# This stage is used when running from VS in fast mode (Default for Debug configuration) +FROM 10.99.253.167:8090/dotnet/runtime:7.0 AS base +WORKDIR /app + + +# This stage is used to build the service project +FROM 10.99.253.167:8090/dotnet/sdk:7.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["NuGet.config", "."] +COPY ["PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj", "PARR.TemplateMatcherWorker/"] +COPY ["PARR.TemplateMatcher/PARR.TemplateMatcher.csproj", "PARR.TemplateMatcher/"] +COPY ["PARR.BLL/PARR.BLL.csproj", "PARR.BLL/"] +COPY ["PARR.Common/PARR.Common.csproj", "PARR.Common/"] +COPY ["PARR.Constants/PARR.Constants.csproj", "PARR.Constants/"] +COPY ["PARR.DAL/PARR.DAL.csproj", "PARR.DAL/"] +RUN dotnet restore "./PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj" +COPY . . +WORKDIR "/src/PARR.TemplateMatcherWorker" +RUN dotnet build "./PARR.TemplateMatcherWorker.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# This stage is used to publish the service project to be copied to the final stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +ARG app_version=0.0.0-default +RUN dotnet publish "./PARR.TemplateMatcherWorker.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false /p:Version=$app_version + +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "PARR.TemplateMatcherWorker.dll"] \ No newline at end of file diff --git a/PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj b/PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj index a066311a..95d8f186 100644 --- a/PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj +++ b/PARR.TemplateMatcherWorker/PARR.TemplateMatcherWorker.csproj @@ -5,11 +5,13 @@ enable enable dotnet-PARR.TemplateMatcherWorker-5320c017-a02a-449c-9b4a-13adca2c3558 + Linux + diff --git a/PARR.TemplateMatcherWorker/Properties/launchSettings.json b/PARR.TemplateMatcherWorker/Properties/launchSettings.json index 4b6f1f77..f5a722d4 100644 --- a/PARR.TemplateMatcherWorker/Properties/launchSettings.json +++ b/PARR.TemplateMatcherWorker/Properties/launchSettings.json @@ -1,11 +1,14 @@ -{ +{ "profiles": { "PARR.TemplateMatcherWorker": { "commandName": "Project", - "dotnetRunMessages": true, "environmentVariables": { "DOTNET_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true + }, + "Container (Dockerfile)": { + "commandName": "Docker" } } -} +} \ No newline at end of file diff --git a/PARR.TemplateTaskGenerator/TemplateTaskGenerator.cs b/PARR.TemplateTaskGenerator/TemplateTaskGenerator.cs index de4e11bc..6522bb06 100644 --- a/PARR.TemplateTaskGenerator/TemplateTaskGenerator.cs +++ b/PARR.TemplateTaskGenerator/TemplateTaskGenerator.cs @@ -32,7 +32,7 @@ namespace PARR.TemplateTaskGenerator public async Task GenerateTemplateTaskAsync(Guid jobId) { - var unitIdsToCreateTemplate = await unitFilterService.GetUnitsIdForNotExistTemplatesByJobFilterAsync(jobId); + var unitIdsToCreateTemplate = await unitFilterService.GetUnitsIdByJobFilterWithTemplateStatusAsync(jobId,false); if (unitIdsToCreateTemplate == null || !unitIdsToCreateTemplate.Any()) return;