From 014c760225404089f859d527eaf9d4a765b7f3bc Mon Sep 17 00:00:00 2001 From: Mikhail Kuznetsov Date: Thu, 25 Jul 2024 17:23:08 +1000 Subject: [PATCH] =?UTF-8?q?feat(templateActivator):=20=D0=9C=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=B4=D1=8B=20=D1=87=D1=82=D0=B5=D0=BD=D0=B8=D1=8F=20MQ,?= =?UTF-8?q?=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D0=B9=20?= =?UTF-8?q?=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2=20=D0=B8=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B9,?= =?UTF-8?q?=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B9=20=D1=80=D0=BE?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TemplateActivatorActionsEnum.cs | 8 +- .../IMqTemplateActivator.cs | 7 ++ PARR.TemplateActivator/ITemplateActivator.cs | 8 ++ PARR.TemplateActivator/MqTemplateActivator.cs | 71 +++++++++++ .../Services/IValidatorService.cs | 8 ++ .../Services/ValidatorService.cs | 42 +++++++ PARR.TemplateActivator/Settings/MqSettings.cs | 12 ++ PARR.TemplateActivator/TemplateActivator.cs | 113 ++++++++++++++++++ .../TemplateActivatorInstaller.cs | 24 ++++ PARR.TemplateActivatorWorker/Program.cs | 33 +++-- PARR.TemplateActivatorWorker/Worker.cs | 19 +-- .../appsettings.Development.json | 3 + PARR.TemplateActivatorWorker/appsettings.json | 27 +++++ 13 files changed, 357 insertions(+), 18 deletions(-) create mode 100644 PARR.TemplateActivator/IMqTemplateActivator.cs create mode 100644 PARR.TemplateActivator/ITemplateActivator.cs create mode 100644 PARR.TemplateActivator/MqTemplateActivator.cs create mode 100644 PARR.TemplateActivator/Services/IValidatorService.cs create mode 100644 PARR.TemplateActivator/Services/ValidatorService.cs create mode 100644 PARR.TemplateActivator/Settings/MqSettings.cs create mode 100644 PARR.TemplateActivator/TemplateActivator.cs create mode 100644 PARR.TemplateActivator/TemplateActivatorInstaller.cs diff --git a/PARR.Constants/TemplateActivatorActionsEnum.cs b/PARR.Constants/TemplateActivatorActionsEnum.cs index 661577dd..64ae3f64 100644 --- a/PARR.Constants/TemplateActivatorActionsEnum.cs +++ b/PARR.Constants/TemplateActivatorActionsEnum.cs @@ -35,14 +35,14 @@ /// DeactivateAllSchedules = 5, - /// + /// /// Активировать все расписания у которых активированы шаблоны - /// + /// ActivateSchedulesWithActiveTemplates = 6, - /// + /// /// Деактивировать все расписания у которых деактивированы шаблоны - /// + /// DeactivateSchedulesWithDeactivationTemplates = 7 diff --git a/PARR.TemplateActivator/IMqTemplateActivator.cs b/PARR.TemplateActivator/IMqTemplateActivator.cs new file mode 100644 index 00000000..02eae893 --- /dev/null +++ b/PARR.TemplateActivator/IMqTemplateActivator.cs @@ -0,0 +1,7 @@ +namespace PARR.TemplateActivator; + +public interface IMqTemplateActivator +{ + void Start(); + void Stop(); +} diff --git a/PARR.TemplateActivator/ITemplateActivator.cs b/PARR.TemplateActivator/ITemplateActivator.cs new file mode 100644 index 00000000..c0d9f359 --- /dev/null +++ b/PARR.TemplateActivator/ITemplateActivator.cs @@ -0,0 +1,8 @@ +using PARR.Constants; + +namespace PARR.TemplateActivator; + +public interface ITemplateActivator +{ + Task ChangeStateAsync(Guid applicationInWorkId, TemplateActivatorActionsEnum action); +} diff --git a/PARR.TemplateActivator/MqTemplateActivator.cs b/PARR.TemplateActivator/MqTemplateActivator.cs new file mode 100644 index 00000000..c3053447 --- /dev/null +++ b/PARR.TemplateActivator/MqTemplateActivator.cs @@ -0,0 +1,71 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using PARR.BLL.Domain.Mq; +using PARR.BLL.Services.Interfaces; +using PARR.Constants; + +namespace PARR.TemplateActivator; + +internal class MqTemplateActivator : IMqTemplateActivator +{ + private readonly MqSettings mqSettings; + private readonly IMqService mqService; + private readonly ILogger logger; + private readonly ITransformService transformService; + private readonly IValidatorService validatorService; + private readonly IServiceProvider serviceProvider; + + public MqTemplateActivator( + MqSettings mqSettings, + IMqService mqService, + ILogger logger, + ITransformService transformService, + IValidatorService validatorService, + IServiceProvider serviceProvider + ) + { + this.mqSettings = mqSettings; + this.mqService = mqService; + this.logger = logger; + this.transformService = transformService; + this.validatorService = validatorService; + this.serviceProvider = serviceProvider; + } + public void Start() + { + var isConnected = mqService.InitConsumer(mqSettings, UpdateTemplateStatusAsync); + + if (!isConnected) + throw new Exception("Ошибка при подключении к RabbitMq"); + } + + private async Task UpdateTemplateStatusAsync(string msg) + { + logger.LogInformation($"{this.GetType().Name}. Получили запрос: {msg}"); + + var query = transformService.GetModelFromJson(msg); + if (query == null) + return; + + if (!await validatorService.IsValidApplicationInWorkAsync(query.ApplicationInWorkId)) + { + logger.LogError($"{this.GetType().Name}. Некорректные параметры регламентной работы {nameof(query.ApplicationInWorkId)}: {query.ApplicationInWorkId}"); + return; + } + + using (var scope = serviceProvider.CreateScope()) + { + var service = scope.ServiceProvider.GetService(); + if (service == null) + throw new Exception($"{this.GetType().Name}. Не найден сервис: {nameof(service.GetType)}"); + + await service.ChangeStateAsync(query.ApplicationInWorkId, query.Action); + + } + } + + public void Stop() + { + mqService.Dispose(); + } +} diff --git a/PARR.TemplateActivator/Services/IValidatorService.cs b/PARR.TemplateActivator/Services/IValidatorService.cs new file mode 100644 index 00000000..86c6de70 --- /dev/null +++ b/PARR.TemplateActivator/Services/IValidatorService.cs @@ -0,0 +1,8 @@ +using PARR.Constants; + +namespace PARR.TemplateActivator; + +internal interface IValidatorService +{ + Task IsValidApplicationInWorkAsync(Guid applicationInWorkId); +} diff --git a/PARR.TemplateActivator/Services/ValidatorService.cs b/PARR.TemplateActivator/Services/ValidatorService.cs new file mode 100644 index 00000000..b4b31388 --- /dev/null +++ b/PARR.TemplateActivator/Services/ValidatorService.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using PARR.Constants; +using PARR.DAL.Services.Interfaces; + +namespace PARR.TemplateActivator; +internal class ValidatorService : IValidatorService +{ + private readonly IServiceProvider serviceProvider; + private readonly ILogger logger; + + public ValidatorService(IServiceProvider serviceProvider, + ILogger logger + ) + { + this.serviceProvider = serviceProvider; + this.logger = logger; + } + + public async Task IsValidApplicationInWorkAsync(Guid applicationInWorkId) + { + using (var scope = serviceProvider.CreateScope()) + { + var service = scope.ServiceProvider.GetService(); + + if (service == null) + throw new Exception($"Не найден сервис: {nameof(IApplicationsInWorkService)}"); + + var appInWork = await service.Get() + .FirstOrDefaultAsync(t => t.Id == applicationInWorkId); + + if (appInWork == null) + { + logger.LogError($"Не найдена регалментная работа {nameof(applicationInWorkId)}: {applicationInWorkId}"); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/PARR.TemplateActivator/Settings/MqSettings.cs b/PARR.TemplateActivator/Settings/MqSettings.cs new file mode 100644 index 00000000..426a9831 --- /dev/null +++ b/PARR.TemplateActivator/Settings/MqSettings.cs @@ -0,0 +1,12 @@ +using PARR.BLL.Contracts.Interfaces; + +namespace PARR.TemplateActivator; + +internal class MqSettings : IMqSettings +{ + public string HostName { get; set; } = string.Empty; + public string QueueName { get; set; } = string.Empty; + public string User { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; +} + diff --git a/PARR.TemplateActivator/TemplateActivator.cs b/PARR.TemplateActivator/TemplateActivator.cs new file mode 100644 index 00000000..29c9bbd2 --- /dev/null +++ b/PARR.TemplateActivator/TemplateActivator.cs @@ -0,0 +1,113 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using PARR.Constants; +using PARR.DAL.Contracts; +using PARR.DAL.Models; +using PARR.DAL.Services.Interfaces; + +namespace PARR.TemplateActivator; + +internal class TemplateActivator : ITemplateActivator +{ + private readonly ILogger logger; + private readonly ITemplateService templateService; + private readonly IRobotConfigurationService robotConfigurationService; + + public TemplateActivator( + ILogger logger, + ITemplateService templateService, + IRobotConfigurationService robotConfigurationService + ) + { + this.logger = logger; + this.templateService = templateService; + this.robotConfigurationService = robotConfigurationService; + } + public async Task ChangeStateAsync(Guid applicationInWorkId, TemplateActivatorActionsEnum action) + { + var query = templateService.Get() + .Include(t => t.RobotConfigurations).ThenInclude(t => t.Robot) + .Where(t => t.ApplicationInWorkId == applicationInWorkId); + var changes = 0; + switch (action) + { + case TemplateActivatorActionsEnum.ActivateAllTemplates: + query = query.Where(t => !t.IsActiveTemplate); + changes = await UpdateTemplateStateAsync(query, true); + break; + case TemplateActivatorActionsEnum.ActivateTemplatesWithActiveSchedules: + query = query.Where(t => !t.IsActiveTemplate && t.IsActiveSchedule); + changes = await UpdateTemplateStateAsync(query, true); + break; + case TemplateActivatorActionsEnum.DeactivateAllTemplates: + query = query.Where(t => t.IsActiveTemplate); + changes = await UpdateTemplateStateAsync(query, false); + break; + case TemplateActivatorActionsEnum.DeactivateTemplatesWithDeactivationSchedules: + query = query.Where(t => !t.IsActiveTemplate && !t.IsActiveSchedule); + changes = await UpdateTemplateStateAsync(query, false); + break; + case TemplateActivatorActionsEnum.ActivateAllSchedules: + query = query.Where(t => !t.IsActiveSchedule); + changes = await UpdateScheduleStateAsync(query, true); + break; + case TemplateActivatorActionsEnum.DeactivateAllSchedules: + query = query.Where(t => t.IsActiveSchedule); + changes = await UpdateScheduleStateAsync(query, false); + break; + case TemplateActivatorActionsEnum.ActivateSchedulesWithActiveTemplates: + query = query.Where(t => t.IsActiveTemplate && !t.IsActiveSchedule); + changes = await UpdateScheduleStateAsync(query, true); + break; + case TemplateActivatorActionsEnum.DeactivateSchedulesWithDeactivationTemplates: + query = query.Where(t => !t.IsActiveTemplate); + changes = await UpdateScheduleStateAsync(query, false); + break; + default: + break; + } + + if (changes > 0 && !await templateService.CommitAsync()) + logger.LogError($"{this.GetType} не удалось записать измения состояний шаблонов и расписаний регламентной работы {applicationInWorkId}"); + + } + + private async Task UpdateScheduleStateAsync(IQueryable