diff --git a/PARR.BLL/Domain/Mq/GeneratorTemplateMq.cs b/PARR.BLL/Domain/Mq/GeneratorTemplateMq.cs index 386600cc..e3788367 100644 --- a/PARR.BLL/Domain/Mq/GeneratorTemplateMq.cs +++ b/PARR.BLL/Domain/Mq/GeneratorTemplateMq.cs @@ -1,5 +1,8 @@ namespace PARR.BLL.Domain.Mq { + /// + /// Модель в MQ, запрос на генерацию шаблона + /// public class GeneratorTemplateMq { /// diff --git a/PARR.GeneratorTemplates/GeneratorTemplate.cs b/PARR.GeneratorTemplates/GeneratorTemplate.cs index a55c33d7..7b5aa93a 100644 --- a/PARR.GeneratorTemplates/GeneratorTemplate.cs +++ b/PARR.GeneratorTemplates/GeneratorTemplate.cs @@ -1,5 +1,10 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using PARR.BLL.Contracts; +using PARR.BLL.Domain.Mq; using PARR.BLL.Services.Interfaces; +using PARR.DAL.Models; +using PARR.GeneratorTemplates.Services; using PARR.GeneratorTemplates.Settings; namespace PARR.GeneratorTemplates @@ -9,41 +14,50 @@ namespace PARR.GeneratorTemplates 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 GeneratorTemplate( MqSettings mqSettings, IMqService mqService, - ILogger logger + 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() + //TODO: метод не async, удалить позже асинк в worker + public async Task Start() { - mqService.Received += (msg) => - { - logger.LogInformation($"Привет откуда надо!!! ${msg}"); - //todo: идем дальеш! + //mqService.Received += async (msg) => - // создать отдельный метод - // преобразовать json в модель - // попробовать поиск по регулярке + //{ + // logger.LogInformation($"Привет откуда надо!!! ${msg}"); + // //todo: идем дальеш! - // проверить как ту дела с асинком - // логгер работает в разных потоках все таки или нет? + string msg = "{\"WorkId\":\"91219bec-e5f7-4a1a-b4c9-c135035d2498\",\"ApplicationId\":\"13044a1f-fa0c-476f-b501-2b8d06bac9f8\",\"Action\":\"deactivate\",\"Ek\":\"вРТ-*RZD\"}"; + await GenerateTemplates(msg); - // поиск в существующих шаблонах, есть ли такие и есть ли у них эти работы - // поиск в хостах эк которых еще нет в шаблонах и у них такие работы - // генерим список и вставляем в шаблоны - }; + // // проверить как ту дела с асинком + // // логгер работает в разных потоках все таки или нет? - var isConnected = mqService.InitConsumer(mqSettings); + //}; - if (!isConnected) - throw new Exception("Ошибка при подключении к RabbitMq"); + + + //var isConnected = mqService.InitConsumer(mqSettings); + + //if (!isConnected) + // throw new Exception("Ошибка при подключении к RabbitMq"); } @@ -52,5 +66,48 @@ namespace PARR.GeneratorTemplates { mqService.Dispose(); } + + + private async Task GenerateTemplates(string msg) + { + logger.LogDebug($"Получили запрос: {msg}"); + + var query = transformService.GetModelFromJson(msg); + if (query == null) + return; + + if (!await validatorService.IsValidApplicationAndWorksAsync(query.ApplicationId, query.WorkId)) + { + logger.LogError($"Невалидны параметры {nameof(query.ApplicationId)}: {query.ApplicationId}, " + + $"{nameof(query.WorkId)}: {query.WorkId}," + + $" нет таких значений или они не связаны в таблице ${nameof(ApplicationsInWork)}"); + return; + } + + Enum.TryParse(typeof(GenerateTemplateActionsEnum), query.Action, true, out var action); + + using (var scope = serviceProvider.CreateScope()) + { + var templateManager = scope.ServiceProvider.GetService(); + if (templateManager == null) + throw new Exception($"Не найден сервис: {nameof(ITemplateManager)}"); + + switch (action) + { + case GenerateTemplateActionsEnum.create: + await templateManager.CreateTemplates(query); + break; + + case GenerateTemplateActionsEnum.deactivate: + await templateManager.DeactivateTemplates(query); + break; + + default: + logger.LogError($"Во входящем запросе, поле {nameof(query.Action)} не содержит допустимых значений"); + return; + } + } + } + } } diff --git a/PARR.GeneratorTemplates/GeneratorTemplateInstaller.cs b/PARR.GeneratorTemplates/GeneratorTemplateInstaller.cs index 4b8d1acf..006ba6d3 100644 --- a/PARR.GeneratorTemplates/GeneratorTemplateInstaller.cs +++ b/PARR.GeneratorTemplates/GeneratorTemplateInstaller.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using PARR.BLL; using PARR.DAL; +using PARR.GeneratorTemplates.Services; using PARR.GeneratorTemplates.Settings; namespace PARR.GeneratorTemplates @@ -20,6 +21,9 @@ namespace PARR.GeneratorTemplates //add other services services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } //2 diff --git a/PARR.GeneratorTemplates/IGeneratorTemplate.cs b/PARR.GeneratorTemplates/IGeneratorTemplate.cs index 89c2f408..ee31a68c 100644 --- a/PARR.GeneratorTemplates/IGeneratorTemplate.cs +++ b/PARR.GeneratorTemplates/IGeneratorTemplate.cs @@ -2,7 +2,7 @@ { public interface IGeneratorTemplate { - void Start(); + Task Start(); void Stop(); } } diff --git a/PARR.GeneratorTemplates/Services/ITemplateManager.cs b/PARR.GeneratorTemplates/Services/ITemplateManager.cs new file mode 100644 index 00000000..ebfb9494 --- /dev/null +++ b/PARR.GeneratorTemplates/Services/ITemplateManager.cs @@ -0,0 +1,10 @@ +using PARR.BLL.Domain.Mq; + +namespace PARR.GeneratorTemplates.Services +{ + internal interface ITemplateManager + { + Task CreateTemplates(GeneratorTemplateMq query); + Task DeactivateTemplates(GeneratorTemplateMq query); + } +} diff --git a/PARR.GeneratorTemplates/Services/ITransformService.cs b/PARR.GeneratorTemplates/Services/ITransformService.cs new file mode 100644 index 00000000..cd81e883 --- /dev/null +++ b/PARR.GeneratorTemplates/Services/ITransformService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PARR.GeneratorTemplates.Services +{ + internal interface ITransformService + { + T? GetModelFromJson(string str); + } +} diff --git a/PARR.GeneratorTemplates/Services/IValidatorService.cs b/PARR.GeneratorTemplates/Services/IValidatorService.cs new file mode 100644 index 00000000..10b8e8c7 --- /dev/null +++ b/PARR.GeneratorTemplates/Services/IValidatorService.cs @@ -0,0 +1,7 @@ +namespace PARR.GeneratorTemplates.Services +{ + internal interface IValidatorService + { + Task IsValidApplicationAndWorksAsync(Guid applicationId, Guid workId); + } +} diff --git a/PARR.GeneratorTemplates/Services/TemplateManager.cs b/PARR.GeneratorTemplates/Services/TemplateManager.cs new file mode 100644 index 00000000..2afdfa6e --- /dev/null +++ b/PARR.GeneratorTemplates/Services/TemplateManager.cs @@ -0,0 +1,71 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using PARR.BLL.Domain.Mq; +using PARR.DAL.Contracts; +using PARR.DAL.Services.Interfaces; + +namespace PARR.GeneratorTemplates.Services +{ + internal class TemplateManager : ITemplateManager + { + private readonly ITemplateService templateService; + private readonly ILogger logger; + + public TemplateManager( + ITemplateService templateService, + ILogger logger + ) + { + this.templateService = templateService; + this.logger = logger; + } + + public async Task CreateTemplates(GeneratorTemplateMq query) + { + //Согласно параметрам, находит все ЭК в таблице Hosts. + //Далее проверяет есть ли такие шаблоны в таблице Templates, если нет, то создает. + //Если такие шаблоны уже есть, ничего с ними не делает. + + //TODO: + } + + public async Task DeactivateTemplates(GeneratorTemplateMq query) + { + //Ищет все активные шаблоны согласно параметрам в таблице Templates, и деактивирует их. Меняем на статус Updating + + // делаем sql форматдля like из запроса. + string pattern = query.Ek.Replace("*", "%").ToLower(); + + var existTemplates = await templateService.Get() + .Include(t => t.Host) + .Include(t => t.ApplicationsInWork) + .Where(t => + t.IsActive == true + && t.ApplicationsInWork!.ApplicationId == query.ApplicationId + && t.ApplicationsInWork!.WorkId == query.WorkId + && EF.Functions.Like(t.Host!.Ek.ToLower(), pattern) + ) + .ToListAsync(); + + if (!existTemplates.Any()) + { + logger.LogInformation("Нет шаблонов для деактивации"); + return; + } + + existTemplates.ForEach(item => + { + item.IsActive = false; + item.StatusCode = (int)StatusTemplateEnum.Updating; + item.DateModified = DateTimeOffset.UtcNow; + }); + + if (await templateService.CommitAsync()) + existTemplates.ForEach(item => logger.LogInformation($"Деактивирован шаблон: {item.Name}")); + else + existTemplates.ForEach(item => logger.LogError($"Ошибка при дактивации шаблона: {item.Name}")); + } + + + } +} diff --git a/PARR.GeneratorTemplates/Services/TransformService.cs b/PARR.GeneratorTemplates/Services/TransformService.cs new file mode 100644 index 00000000..c539f8b9 --- /dev/null +++ b/PARR.GeneratorTemplates/Services/TransformService.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.Logging; +using System.Text.Json; + +namespace PARR.GeneratorTemplates.Services +{ + internal class TransformService : ITransformService + { + private readonly ILogger logger; + + public TransformService(ILogger logger) + { + this.logger = logger; + } + + public T? GetModelFromJson(string str) + { + try + { + return JsonSerializer.Deserialize(str); + } + catch (Exception ex) + { + logger.LogError(ex, $"Ошибка при конвертации строки в модель. {str}"); + + return default; + } + } + } +} diff --git a/PARR.GeneratorTemplates/Services/ValidatorService.cs b/PARR.GeneratorTemplates/Services/ValidatorService.cs new file mode 100644 index 00000000..10758ad7 --- /dev/null +++ b/PARR.GeneratorTemplates/Services/ValidatorService.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.DependencyInjection; +using PARR.DAL.Services.Interfaces; + +namespace PARR.GeneratorTemplates.Services +{ + internal class ValidatorService : IValidatorService + { + private readonly IServiceProvider serviceProvider; + + public ValidatorService(IServiceProvider serviceProvider) + { + this.serviceProvider = serviceProvider; + } + + /// + /// Проверка, валидны ли поля и связана ли Работа с Приложением + /// + /// + /// + /// + public async Task IsValidApplicationAndWorksAsync(Guid applicationId, Guid workId) + { + using (var scope = serviceProvider.CreateScope()) + { + var service = scope.ServiceProvider.GetService(); + + if (service == null) + throw new Exception($"Не найден сервис: {nameof(IApplicationsInWorkService)}"); + + return await service.Get(applicationId, workId) != null; + } + } + } +} diff --git a/PARR.GeneratorTemplatesWorker/Worker.cs b/PARR.GeneratorTemplatesWorker/Worker.cs index 7f1ec28a..a8bd5af8 100644 --- a/PARR.GeneratorTemplatesWorker/Worker.cs +++ b/PARR.GeneratorTemplatesWorker/Worker.cs @@ -16,7 +16,7 @@ namespace PARR.GeneratorTemplatesWorker protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // todo: обернуть в таск? - generatorTemplate.Start(); + await generatorTemplate.Start(); //while (!stoppingToken.IsCancellationRequested) //{ // _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); diff --git a/PARR.GeneratorTemplatesWorker/appsettings.json b/PARR.GeneratorTemplatesWorker/appsettings.json index c4246afa..6615570a 100644 --- a/PARR.GeneratorTemplatesWorker/appsettings.json +++ b/PARR.GeneratorTemplatesWorker/appsettings.json @@ -1,4 +1,7 @@ { + "ConnectionStrings": { + "DefaultConnection": "Server=10.99.253.184;Database=parr;User Id=app_parr; Password=PosdfkhT&)%sdfligL&%5546;" + }, "Logging": { "LogLevel": { "Default": "Information",