diff --git a/PARR.AIHITMainSyncer/Services/SyncerService.cs b/PARR.AIHITMainSyncer/Services/SyncerService.cs index 2acb0e1d..53b3a228 100644 --- a/PARR.AIHITMainSyncer/Services/SyncerService.cs +++ b/PARR.AIHITMainSyncer/Services/SyncerService.cs @@ -35,7 +35,7 @@ namespace PARR.AIHITMainSyncer.Services public async Task SyncAsync(string msg) { - logger.LogInformation("Запуск синхронизации данных из очереди сообщений в ПАРР."); + //logger.LogInformation("Запуск синхронизации данных из очереди сообщений в ПАРР."); var objFromQuery = transformService.GetModelFromJson(msg); if (objFromQuery == null) return; diff --git a/PARR.API.sln b/PARR.API.sln index 898fdffb..f7fd1fa2 100644 --- a/PARR.API.sln +++ b/PARR.API.sln @@ -92,6 +92,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.AIHITRelationshipsSync EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.TemplateGeneratorWorker", "PARR.TemplateGeneratorWorker\PARR.TemplateGeneratorWorker.csproj", "{17245D0B-3290-4C96-B5B1-4B0711BABAF2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.TemplateTaskGenerator", "TemplateTaskGenerator\PARR.TemplateTaskGenerator.csproj", "{D4C51090-CE06-4158-9A0E-961744872411}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PARR.TemplateTaskGeneratorWorker", "TemplateTaskGeneratorWorker\PARR.TemplateTaskGeneratorWorker.csproj", "{93249642-DF7D-41A1-87C0-6E3BAECB43EC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -256,6 +260,14 @@ Global {17245D0B-3290-4C96-B5B1-4B0711BABAF2}.Debug|Any CPU.Build.0 = Debug|Any CPU {17245D0B-3290-4C96-B5B1-4B0711BABAF2}.Release|Any CPU.ActiveCfg = Release|Any CPU {17245D0B-3290-4C96-B5B1-4B0711BABAF2}.Release|Any CPU.Build.0 = Release|Any CPU + {D4C51090-CE06-4158-9A0E-961744872411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4C51090-CE06-4158-9A0E-961744872411}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4C51090-CE06-4158-9A0E-961744872411}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4C51090-CE06-4158-9A0E-961744872411}.Release|Any CPU.Build.0 = Release|Any CPU + {93249642-DF7D-41A1-87C0-6E3BAECB43EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93249642-DF7D-41A1-87C0-6E3BAECB43EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93249642-DF7D-41A1-87C0-6E3BAECB43EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93249642-DF7D-41A1-87C0-6E3BAECB43EC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PARR.BLL/Domain/Mq/TemplateTaskGeneratorMq.cs b/PARR.BLL/Domain/Mq/TemplateTaskGeneratorMq.cs new file mode 100644 index 00000000..854c9aa4 --- /dev/null +++ b/PARR.BLL/Domain/Mq/TemplateTaskGeneratorMq.cs @@ -0,0 +1,13 @@ +namespace PARR.BLL.Domain.Mq +{ + /// + /// Модель в MQ, генератора заданий на генерацию шаблонов + /// + public class TemplateTaskGeneratorMq + { + /// + /// Id регламентной работы + /// + public Guid JobId { get; set; } + } +} diff --git a/PARR.Constants/ParrComponentsEnum.cs b/PARR.Constants/ParrComponentsEnum.cs index ac3f1091..64f47846 100644 --- a/PARR.Constants/ParrComponentsEnum.cs +++ b/PARR.Constants/ParrComponentsEnum.cs @@ -76,6 +76,6 @@ /// /// Генератор Template /// - TemplateGenerator = 13 + TemplateTaskGenerator = 13 } } diff --git a/PARR.TemplateActivator/MqTemplateActivator.cs b/PARR.TemplateActivator/MqTemplateActivator.cs index b08e303a..aa83e92c 100644 --- a/PARR.TemplateActivator/MqTemplateActivator.cs +++ b/PARR.TemplateActivator/MqTemplateActivator.cs @@ -2,8 +2,6 @@ using Microsoft.Extensions.Logging; using PARR.BLL.Domain.Mq; using PARR.BLL.Services.Interfaces; -using PARR.Constants; -using System.Threading.Tasks; namespace PARR.TemplateActivator; @@ -67,6 +65,6 @@ internal class MqTemplateActivator : IMqTemplateActivator public async Task StopAsync() { - await mqService.DisposeAsync(); + await mqService.DisposeAsync(); } } diff --git a/PARR.TemplateActivator/Services/ValidatorService.cs b/PARR.TemplateActivator/Services/ValidatorService.cs index af645101..ba03976f 100644 --- a/PARR.TemplateActivator/Services/ValidatorService.cs +++ b/PARR.TemplateActivator/Services/ValidatorService.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using PARR.Constants; using PARR.DAL.Services.Interfaces; namespace PARR.TemplateActivator; diff --git a/TemplateTaskGenerator/IMqTemplateTaskGenerator.cs b/TemplateTaskGenerator/IMqTemplateTaskGenerator.cs new file mode 100644 index 00000000..88e14433 --- /dev/null +++ b/TemplateTaskGenerator/IMqTemplateTaskGenerator.cs @@ -0,0 +1,8 @@ +namespace PARR.TemplateTaskGenerator +{ + public interface IMqTemplateTaskGenerator + { + Task StartAsync(); + Task StopAsync(); + } +} diff --git a/TemplateTaskGenerator/ITemplateTaskGenerator.cs b/TemplateTaskGenerator/ITemplateTaskGenerator.cs new file mode 100644 index 00000000..36f08b50 --- /dev/null +++ b/TemplateTaskGenerator/ITemplateTaskGenerator.cs @@ -0,0 +1,7 @@ +namespace PARR.TemplateTaskGenerator +{ + internal interface ITemplateTaskGenerator + { + Task GenerateTemplateTaskAsync(Guid jobId); + } +} diff --git a/TemplateTaskGenerator/MqTemplateTaskGenerator.cs b/TemplateTaskGenerator/MqTemplateTaskGenerator.cs new file mode 100644 index 00000000..1c519f11 --- /dev/null +++ b/TemplateTaskGenerator/MqTemplateTaskGenerator.cs @@ -0,0 +1,79 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using PARR.BLL.Domain.Mq; +using PARR.BLL.Services.Interfaces; +using PARR.TemplateTaskGenerator.Services; +using PARR.TemplateTaskGenerator.Settings; + +namespace PARR.TemplateTaskGenerator +{ + internal class MqTemplateTaskGenerator : IMqTemplateTaskGenerator + { + private readonly ILogger logger; + private readonly MqSettings mqSettings; + private readonly IMqService mqService; + private readonly ITransformService transformService; + private readonly IServiceProvider serviceProvider; + + public MqTemplateTaskGenerator( + ILogger logger, + MqSettings mqSettings, + IMqService mqService, + ITransformService transformService, + IServiceProvider serviceProvider + ) + { + this.logger = logger; + this.mqSettings = mqSettings; + this.mqService = mqService; + this.transformService = transformService; + this.serviceProvider = serviceProvider; + } + + + public async Task StartAsync() + { + var isConnected = await mqService.InitConsumerAsync(mqSettings.TemplateTaskGenerator, GenerateTemplateTaskAsync); + + if (!isConnected) + throw new Exception("Ошибка при подключении к RabbitMq"); + } + + + public async Task StopAsync() + { + await mqService.DisposeAsync(); + } + + + private async Task GenerateTemplateTaskAsync(string msg) + { + logger.LogInformation($"Получили запрос: {msg}"); + + var query = transformService.GetModelFromJson(msg); + if (query == null) + return; + + await using (var scope = serviceProvider.CreateAsyncScope()) + { + var validatorService = GetServiceInScope(scope); + if (!await validatorService.IsValidAsync(query.JobId)) + return; + + var templateTaskGenerator = GetServiceInScope(scope); + await templateTaskGenerator.GenerateTemplateTaskAsync(query.JobId); + + } + } + + + private Service GetServiceInScope(IServiceScope scope) + { + var service = scope.ServiceProvider.GetService(); + if (service == null) + throw new Exception($"Не найден сервис: {nameof(Service)}"); + + return service; + } + } +} diff --git a/TemplateTaskGenerator/PARR.TemplateTaskGenerator.csproj b/TemplateTaskGenerator/PARR.TemplateTaskGenerator.csproj new file mode 100644 index 00000000..21190861 --- /dev/null +++ b/TemplateTaskGenerator/PARR.TemplateTaskGenerator.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + + diff --git a/TemplateTaskGenerator/Services/IValidatorService.cs b/TemplateTaskGenerator/Services/IValidatorService.cs new file mode 100644 index 00000000..0bce2004 --- /dev/null +++ b/TemplateTaskGenerator/Services/IValidatorService.cs @@ -0,0 +1,12 @@ +namespace PARR.TemplateTaskGenerator.Services +{ + internal interface IValidatorService + { + /// + /// Проверяет существование регламентной работы + /// + /// + /// + Task IsValidAsync(Guid jobId); + } +} diff --git a/TemplateTaskGenerator/Services/ValidatorService.cs b/TemplateTaskGenerator/Services/ValidatorService.cs new file mode 100644 index 00000000..d8b7f331 --- /dev/null +++ b/TemplateTaskGenerator/Services/ValidatorService.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Logging; +using PARR.DAL.Services.Interfaces.Job; + +namespace PARR.TemplateTaskGenerator.Services +{ + internal class ValidatorService : IValidatorService + { + private readonly ILogger logger; + private readonly IJobService jobService; + + + public ValidatorService( + ILogger logger, + IJobService jobService + ) + { + this.logger = logger; + this.jobService = jobService; + } + + + public async Task IsValidAsync(Guid jobId) + { + var isExist = await jobService.GetAsync(jobId); + + if (isExist == null) + { + logger.LogError($"Не найдена регалментная работа {nameof(jobId)}: {jobId}"); + return false; + } + + return true; + } + + } +} diff --git a/TemplateTaskGenerator/Settings/MqSettings.cs b/TemplateTaskGenerator/Settings/MqSettings.cs new file mode 100644 index 00000000..a3488c2b --- /dev/null +++ b/TemplateTaskGenerator/Settings/MqSettings.cs @@ -0,0 +1,30 @@ +using PARR.BLL.Contracts.Interfaces; + +namespace PARR.TemplateTaskGenerator.Settings +{ + internal class MqSettings + { + public TemplateTaskGenerator TemplateTaskGenerator { get; set; } = new TemplateTaskGenerator(); + public TemplateGeneratorWorker TemplateGeneratorWorker { get; set; } = new TemplateGeneratorWorker(); + } + + + internal class TemplateTaskGenerator : 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; + public ushort? PrefetchCount { get; set; } = 0; + } + + + internal class TemplateGeneratorWorker : 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; + public ushort? PrefetchCount { get; set; } = 0; + } +} diff --git a/TemplateTaskGenerator/TemplateTaskGenerator.cs b/TemplateTaskGenerator/TemplateTaskGenerator.cs new file mode 100644 index 00000000..de4e11bc --- /dev/null +++ b/TemplateTaskGenerator/TemplateTaskGenerator.cs @@ -0,0 +1,60 @@ +using Microsoft.Extensions.Logging; +using PARR.BLL.Domain.Mq; +using PARR.BLL.Services.Interfaces; +using PARR.Common.Domain; +using PARR.Constants; +using PARR.DAL.DomainServices.Interfaces; +using PARR.TemplateTaskGenerator.Settings; +using System.Text.Json; + +namespace PARR.TemplateTaskGenerator +{ + internal class TemplateTaskGenerator : ITemplateTaskGenerator + { + private readonly ILogger logger; + private readonly IUnitFilterService unitFilterService; + private readonly MqSettings mqSettings; + private readonly IMqService mqService; + + public TemplateTaskGenerator( + ILogger logger, + IUnitFilterService unitFilterService, + MqSettings mqSettings, + IMqService mqService + ) + { + this.logger = logger; + this.unitFilterService = unitFilterService; + this.mqSettings = mqSettings; + this.mqService = mqService; + } + + + public async Task GenerateTemplateTaskAsync(Guid jobId) + { + var unitIdsToCreateTemplate = await unitFilterService.GetUnitsIdForNotExistTemplatesByJobFilterAsync(jobId); + + if (unitIdsToCreateTemplate == null || !unitIdsToCreateTemplate.Any()) + return; + + foreach (var unitId in unitIdsToCreateTemplate) + { + var mqRequest = new TemplateGeneratorWorkerMq + { + JobId = jobId, + UnitId = unitId, + HistoryInitiator = new HistoryInitiator { InitiatorComment = "Запрос на создание шаблона", InitiatorParrComponentId = ParrComponentsEnum.TemplateTaskGenerator } + }; + + var msg = JsonSerializer.Serialize(mqRequest); + + var result = await mqService.SendAsync(mqSettings.TemplateGeneratorWorker, new[] { msg }); + + if (result.IsSuccess) + logger.LogInformation($"Отправлен запрос на создание шаблона: {msg}"); + else + logger.LogError($"Ошибка при отправке запроса на создание шаблона: {msg}"); + } + } + } +} diff --git a/TemplateTaskGenerator/TemplateTaskGeneratorInstaller.cs b/TemplateTaskGenerator/TemplateTaskGeneratorInstaller.cs new file mode 100644 index 00000000..7463656e --- /dev/null +++ b/TemplateTaskGenerator/TemplateTaskGeneratorInstaller.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using PARR.BLL; +using PARR.DAL; +using PARR.TemplateTaskGenerator.Services; +using PARR.TemplateTaskGenerator.Settings; + +namespace PARR.TemplateTaskGenerator +{ + public static class TemplateTaskGeneratorInstaller + { + public static void InstallTemplateTaskGeneratorSerivces(this IServiceCollection services, IConfiguration configuration) + { + services.InstallBllServices(configuration); + services.InstallDalServices(configuration); + + var mqSettings = new MqSettings(); + configuration.GetSection(nameof(MqSettings)).Bind(mqSettings); + services.AddSingleton(mqSettings); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + } + + public static IConfigurationBuilder AddTemplateTaskGeneratorConfigurations(this IConfigurationBuilder builder, IServiceCollection services) + { + builder.AddDalConfigurations(services); + + return builder; + } + + public static void AddTemplateTaskGeneratorSettings(this IServiceCollection services, IConfiguration configuration) + { + services.AddDallSettings(configuration); + } + } +} diff --git a/TemplateTaskGeneratorWorker/PARR.TemplateTaskGeneratorWorker.csproj b/TemplateTaskGeneratorWorker/PARR.TemplateTaskGeneratorWorker.csproj new file mode 100644 index 00000000..b9293df5 --- /dev/null +++ b/TemplateTaskGeneratorWorker/PARR.TemplateTaskGeneratorWorker.csproj @@ -0,0 +1,22 @@ + + + + net7.0 + enable + enable + dotnet-TemplateTaskGeneratorWorker-31809d29-599f-4a6d-8700-45ea8d9e7649 + + + + + + + + + + + + + + + diff --git a/TemplateTaskGeneratorWorker/Program.cs b/TemplateTaskGeneratorWorker/Program.cs new file mode 100644 index 00000000..01af1c88 --- /dev/null +++ b/TemplateTaskGeneratorWorker/Program.cs @@ -0,0 +1,31 @@ +using Elastic.CommonSchema.Serilog; +using PARR.TemplateTaskGenerator; +using PARR.TemplateTaskGeneratorWorker; +using Serilog; + +var builder = Host.CreateApplicationBuilder(); + +builder.Services.AddLogging(config => +{ + config.ClearProviders(); + + var logger = new LoggerConfiguration(); + + if (builder.Environment.IsProduction()) + logger.WriteTo.Console(new EcsTextFormatter()); + else + logger.WriteTo.Console(); + + logger.ReadFrom.Configuration(builder.Configuration); + + config.AddSerilog(logger.CreateLogger()); +}); + +builder.Services.InstallTemplateTaskGeneratorSerivces(builder.Configuration); +builder.Configuration.AddTemplateTaskGeneratorConfigurations(builder.Services); +builder.Services.AddTemplateTaskGeneratorSettings(builder.Configuration); + +builder.Services.AddHostedService(); + +var host = builder.Build(); +host.Run(); \ No newline at end of file diff --git a/TemplateTaskGeneratorWorker/Properties/launchSettings.json b/TemplateTaskGeneratorWorker/Properties/launchSettings.json new file mode 100644 index 00000000..f349ae0f --- /dev/null +++ b/TemplateTaskGeneratorWorker/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "TemplateTaskGeneratorWorker": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/TemplateTaskGeneratorWorker/Worker.cs b/TemplateTaskGeneratorWorker/Worker.cs new file mode 100644 index 00000000..369ab7b7 --- /dev/null +++ b/TemplateTaskGeneratorWorker/Worker.cs @@ -0,0 +1,32 @@ +using PARR.TemplateTaskGenerator; + +namespace PARR.TemplateTaskGeneratorWorker +{ + public class Worker : BackgroundService + { + private readonly ILogger _logger; + private readonly IMqTemplateTaskGenerator mqTemplateTaskGenerator; + + public Worker( + ILogger logger, + IMqTemplateTaskGenerator mqTemplateTaskGenerator + ) + { + _logger = logger; + this.mqTemplateTaskGenerator = mqTemplateTaskGenerator; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + await mqTemplateTaskGenerator.StartAsync(); + } + + + public override Task StopAsync(CancellationToken cancellationToken) + { + mqTemplateTaskGenerator.StopAsync().Wait(); + + return base.StopAsync(cancellationToken); + } + } +} diff --git a/TemplateTaskGeneratorWorker/appsettings.Development.json b/TemplateTaskGeneratorWorker/appsettings.Development.json new file mode 100644 index 00000000..95ce520b --- /dev/null +++ b/TemplateTaskGeneratorWorker/appsettings.Development.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MqSettings": { + "TemplateTaskGenerator": { "HostName": "10.99.253.216" }, + "TemplateGeneratorWorker": { "HostName": "10.99.253.216" } + } +} \ No newline at end of file diff --git a/TemplateTaskGeneratorWorker/appsettings.json b/TemplateTaskGeneratorWorker/appsettings.json new file mode 100644 index 00000000..9cb3fdce --- /dev/null +++ b/TemplateTaskGeneratorWorker/appsettings.json @@ -0,0 +1,45 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=10.99.253.184;Database=parr;User Id=app_parr; Password=PosdfkhT&)%sdfligL&%5546;", + "RedisConnection": "parr-redis:6379,password=ParrP@ssPtk202MMdevDvs" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Debug" + } + }, + "WriteTo": [ + { + "Name": "File", + "Args": { + "path": "log/log-.txt", + "rollingInterval": "Day" + } + } + ] + }, + "MqSettings": { + "TemplateTaskGenerator": { + "HostName": "parr-rabbitmq", + "QueueName": "parr-template-task-generator", + "User": "template_task_generator_reader", + "Password": "wzqj$Z@3:poz@oot" + }, + "TemplateGeneratorWorker": { + "HostName": "parr-rabbitmq", + "QueueName": "parr-template-generator", + "User": "template_generator_writer", + "Password": "B;6h+yF$zQ0OSkLX" + } + + } +} \ No newline at end of file