feat(bll, all): обновлена библиотека RabbitMq.Client до версии 7.1.2. Обновлен MqServiceV2. В IMqSettings добавлен параметр PrefetchCount - макс кол-во одновременных обработок очередей. Обновлены связанные проекты под новый MqService. В проектах Aihit, SyncTemplate, SyncSchedule установлен параметр в конфиг PrefetchCount =100
This commit is contained in:
@@ -64,7 +64,7 @@ namespace PARR.AIHITLoader
|
|||||||
for (var i = 0; i < parts; i++)
|
for (var i = 0; i < parts; i++)
|
||||||
{
|
{
|
||||||
var batch = preparedData.Skip(i * loaderSettings.PackageSize).Take(loaderSettings.PackageSize).ToList();
|
var batch = preparedData.Skip(i * loaderSettings.PackageSize).Take(loaderSettings.PackageSize).ToList();
|
||||||
var sendResult = mqService.Send(mqSettings, batch.ToArray());
|
var sendResult = await mqService.SendAsync(mqSettings, batch.ToArray());
|
||||||
if (sendResult.IsSuccess)
|
if (sendResult.IsSuccess)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Данные переданы в RabbitMQ: {batch.Count()}");
|
logger.LogInformation($"Данные переданы в RabbitMQ: {batch.Count()}");
|
||||||
@@ -75,7 +75,7 @@ namespace PARR.AIHITLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
await Task.CompletedTask;
|
// await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.AIHITLoader.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace PARR.AIHITMainLoader
|
|||||||
for (var i = 0; i < parts; i++)
|
for (var i = 0; i < parts; i++)
|
||||||
{
|
{
|
||||||
var batch = preparedData.Skip(i * loaderSettings.PackageSize).Take(loaderSettings.PackageSize).ToList();
|
var batch = preparedData.Skip(i * loaderSettings.PackageSize).Take(loaderSettings.PackageSize).ToList();
|
||||||
var sendResult = mqService.Send(mqSettings, batch.ToArray());
|
var sendResult = await mqService.SendAsync(mqSettings, batch.ToArray());
|
||||||
if (sendResult.IsSuccess)
|
if (sendResult.IsSuccess)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Данные переданы в RabbitMQ: {batch.Count()}");
|
logger.LogInformation($"Данные переданы в RabbitMQ: {batch.Count()}");
|
||||||
@@ -87,7 +87,7 @@ namespace PARR.AIHITMainLoader
|
|||||||
logger.LogError($"Ошибка при передаче данных в Rabbit, не переданные сообщения: {string.Join(", ", sendResult.NotSendMessages!)}");
|
logger.LogError($"Ошибка при передаче данных в Rabbit, не переданные сообщения: {string.Join(", ", sendResult.NotSendMessages!)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.CompletedTask;
|
// await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ namespace PARR.AIHITMainLoader.Settings
|
|||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ namespace PARR.AIHITMainSyncer
|
|||||||
this.mqSettings = mqSettings;
|
this.mqSettings = mqSettings;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
logger.LogInformation("Запуск сервиса синхронизации данных из АИХИТ и ПАРР.");
|
logger.LogInformation("Запуск сервиса синхронизации данных из АИХИТ и ПАРР.");
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, async (string msg) =>
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, async (string msg) =>
|
||||||
{
|
{
|
||||||
using (var scope = serviceProvider.CreateScope())
|
using (var scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -47,9 +47,9 @@ namespace PARR.AIHITMainSyncer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
{
|
{
|
||||||
public interface IAihitMainSyncer
|
public interface IAihitMainSyncer
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
|
|
||||||
|
Task StopAsync();
|
||||||
void Stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ namespace PARR.AIHITMainSyncer.Settings
|
|||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using PARR.AIHITSyncer.Services;
|
using PARR.AIHITSyncer.Services;
|
||||||
using PARR.AIHITSyncer.Settings;
|
using PARR.AIHITSyncer.Settings;
|
||||||
using PARR.BLL.Services.Interfaces;
|
using PARR.BLL.Services.Interfaces;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PARR.AIHITSyncer
|
namespace PARR.AIHITSyncer
|
||||||
{
|
{
|
||||||
@@ -27,12 +28,12 @@ namespace PARR.AIHITSyncer
|
|||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
logger.LogInformation("Запуск сервиса синхронизации данных из АИХИТ и ПАРР.");
|
logger.LogInformation("Запуск сервиса синхронизации данных из АИХИТ и ПАРР.");
|
||||||
//var isConnected = mqService.InitConsumer(mqSettings, SyncDataAsync);
|
//var isConnected = mqService.InitConsumer(mqSettings, SyncDataAsync);
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, async (string msg) =>
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, async (string msg) =>
|
||||||
{
|
{
|
||||||
using (var scope = serviceProvider.CreateScope())
|
using (var scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -48,9 +49,9 @@ namespace PARR.AIHITSyncer
|
|||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
}
|
}
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IAihitSyncer
|
public interface IAihitSyncer
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.AIHITSyncer.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ namespace PARR.AIHITSyncerWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
aihitSyncer.Start();
|
await aihitSyncer.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
aihitSyncer.Stop();
|
aihitSyncer.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"HostName": "10.99.253.216",
|
"HostName": "10.99.253.216",
|
||||||
"QueueName": "parr-aihit-data",
|
"QueueName": "parr-aihit-data",
|
||||||
"User": "aihit_syncer",
|
"User": "aihit_syncer",
|
||||||
"Password": "afsdgDGjhfiU76496as42!@"
|
"Password": "afsdgDGjhfiU76496as42!@",
|
||||||
|
"PrefetchCount": 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace PARR.API.Controllers.V1
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(requestToMq);
|
var msg = JsonSerializer.Serialize(requestToMq);
|
||||||
|
|
||||||
var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg });
|
var sendResult = await mqService.SendAsync(mqSettings.TemplateDistributor, new[] { msg });
|
||||||
|
|
||||||
if (sendResult.IsSuccess)
|
if (sendResult.IsSuccess)
|
||||||
return Created("", new Response<string?>(null, true, new List<ErrorModel>(), "Отправлен запрос на перераспределение регламентных работ."));
|
return Created("", new Response<string?>(null, true, new List<ErrorModel>(), "Отправлен запрос на перераспределение регламентных работ."));
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ namespace PARR.API.Controllers.V1
|
|||||||
|
|
||||||
request.Ek.ForEach(ek =>
|
request.Ek.ForEach(ek =>
|
||||||
{
|
{
|
||||||
request.Status.ForEach(status =>
|
//todo: проверить в ForEach(async status - отрабатывает ли нормально async, возможно надо переделать в обычный foreach
|
||||||
|
request.Status.ForEach(async status =>
|
||||||
{
|
{
|
||||||
var obj = new GeneratorTemplateMq
|
var obj = new GeneratorTemplateMq
|
||||||
{
|
{
|
||||||
@@ -70,7 +71,7 @@ namespace PARR.API.Controllers.V1
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(obj);
|
var msg = JsonSerializer.Serialize(obj);
|
||||||
|
|
||||||
var _result = mqService.Send(mqSettings.GenerateTemplates, new[] { msg });
|
var _result = await mqService.SendAsync(mqSettings.GenerateTemplates, new[] { msg });
|
||||||
|
|
||||||
if (_result.IsSuccess == false)
|
if (_result.IsSuccess == false)
|
||||||
result = false;
|
result = false;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace PARR.API.Controllers.V1
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(mqRequest);
|
var msg = JsonSerializer.Serialize(mqRequest);
|
||||||
|
|
||||||
var sendResult = mqService.Send(mqSettings.TemplateActivator, new[] { msg });
|
var sendResult = await mqService.SendAsync(mqSettings.TemplateActivator, new[] { msg });
|
||||||
|
|
||||||
if (!sendResult.IsSuccess)
|
if (!sendResult.IsSuccess)
|
||||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при отправке данных." } }));
|
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при отправке данных." } }));
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace PARR.API.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MqTemplateDistributor : IMqSettings
|
public class MqTemplateDistributor : IMqSettings
|
||||||
@@ -24,6 +25,7 @@ namespace PARR.API.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MqTemplateActivator : IMqSettings
|
public class MqTemplateActivator : IMqSettings
|
||||||
@@ -32,6 +34,7 @@ namespace PARR.API.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MqStatistics
|
public class MqStatistics
|
||||||
@@ -45,5 +48,6 @@ namespace PARR.API.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,9 @@
|
|||||||
string QueueName { get; set; }
|
string QueueName { get; set; }
|
||||||
string User { get; set; }
|
string User { get; set; }
|
||||||
string Password { get; set; }
|
string Password { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Кол-во сообщений которые может принимать consumer за один раз. 0 или null - без ограничений
|
||||||
|
/// </summary>
|
||||||
|
ushort? PrefetchCount { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
|
<PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ namespace PARR.BLL
|
|||||||
|
|
||||||
|
|
||||||
services.AddTransient<IFileService, FileService>();
|
services.AddTransient<IFileService, FileService>();
|
||||||
services.AddTransient<IMqService, MqService>();
|
|
||||||
|
//services.AddTransient<IMqService, MqService>();
|
||||||
|
services.AddTransient<IMqService, MqServiceV2>();
|
||||||
|
|
||||||
services.AddHttpClient<IMqAdminService, MqAdminService>();
|
services.AddHttpClient<IMqAdminService, MqAdminService>();
|
||||||
services.AddTransient<ITransformService, TransformService>();
|
services.AddTransient<ITransformService, TransformService>();
|
||||||
services.AddTransient<IIntervalService, IntervalService>();
|
services.AddTransient<IIntervalService, IntervalService>();
|
||||||
|
|||||||
@@ -4,18 +4,19 @@ using PARR.BLL.Domain.Mq;
|
|||||||
using PARR.BLL.Services.Interfaces;
|
using PARR.BLL.Services.Interfaces;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using RabbitMQ.Client.Events;
|
using RabbitMQ.Client.Events;
|
||||||
using System.Runtime;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace PARR.BLL.Services.Implementations
|
namespace PARR.BLL.Services.Implementations
|
||||||
{
|
{
|
||||||
|
|
||||||
internal class MqService : IMqService
|
// RabbitMqClient 6.5.0
|
||||||
|
|
||||||
|
internal class MqService// : IMqService
|
||||||
{
|
{
|
||||||
private readonly ILogger<MqService> logger;
|
private readonly ILogger<MqService> logger;
|
||||||
|
|
||||||
private IConnection? connection;
|
private IConnection? connection;
|
||||||
private IModel? channel;
|
//private IModel? channel;
|
||||||
|
|
||||||
public MqService(ILogger<MqService> logger)
|
public MqService(ILogger<MqService> logger)
|
||||||
{
|
{
|
||||||
@@ -24,144 +25,148 @@ namespace PARR.BLL.Services.Implementations
|
|||||||
|
|
||||||
public MqSendResult Send(IMqSettings mqSettings, string[] msgList)
|
public MqSendResult Send(IMqSettings mqSettings, string[] msgList)
|
||||||
{
|
{
|
||||||
var factory = new ConnectionFactory
|
return new MqSendResult { IsSuccess = false, NotSendMessages = new string[0] };
|
||||||
{
|
|
||||||
HostName = mqSettings.HostName,
|
|
||||||
UserName = mqSettings.User,
|
|
||||||
Password = mqSettings.Password
|
|
||||||
};
|
|
||||||
|
|
||||||
// индекс текущей отправки в очередь из массива msgList
|
//var factory = new ConnectionFactory
|
||||||
// нужен для формирования списка неотправленных сообщений
|
//{
|
||||||
var sendIdx = 0;
|
// HostName = mqSettings.HostName,
|
||||||
|
// UserName = mqSettings.User,
|
||||||
|
// Password = mqSettings.Password
|
||||||
|
//};
|
||||||
|
|
||||||
try
|
//// индекс текущей отправки в очередь из массива msgList
|
||||||
{
|
//// нужен для формирования списка неотправленных сообщений
|
||||||
using (var connection = factory.CreateConnection())
|
//var sendIdx = 0;
|
||||||
using (var channel = connection.CreateModel())
|
|
||||||
{
|
|
||||||
//https://www.rabbitmq.com/lazy-queues.html
|
|
||||||
//Рекомендовано при работе порциями использовать ленивые очереди. сообщения не используют память
|
|
||||||
//Формируем соответствующий аргумент
|
|
||||||
var args = new Dictionary<string, object> { { "x-queue-mode", "lazy" } };
|
|
||||||
|
|
||||||
//Объявляем очередь с которой будем работать.
|
//try
|
||||||
//Если такой очереди ещё нет, то создатся.
|
//{
|
||||||
//Если нет, нужно параметры типа durable должны совпадать иначе будет ошибка.
|
// using (var connection = factory.CreateConnection())
|
||||||
//В целом эти параметры можно посмотреть в админке RabbitMQ
|
// using (var channel = connection.CreateModel())
|
||||||
|
// {
|
||||||
|
// //https://www.rabbitmq.com/lazy-queues.html
|
||||||
|
// //Рекомендовано при работе порциями использовать ленивые очереди. сообщения не используют память
|
||||||
|
// //Формируем соответствующий аргумент
|
||||||
|
// var args = new Dictionary<string, object> { { "x-queue-mode", "lazy" } };
|
||||||
|
|
||||||
channel.QueueDeclare(
|
// //Объявляем очередь с которой будем работать.
|
||||||
queue: mqSettings.QueueName,
|
// //Если такой очереди ещё нет, то создатся.
|
||||||
durable: true,
|
// //Если нет, нужно параметры типа durable должны совпадать иначе будет ошибка.
|
||||||
exclusive: false,
|
// //В целом эти параметры можно посмотреть в админке RabbitMQ
|
||||||
autoDelete: false,
|
|
||||||
arguments: args
|
|
||||||
);
|
|
||||||
|
|
||||||
var props = channel.CreateBasicProperties();
|
// channel.QueueDeclare(
|
||||||
//храним на диске
|
// queue: mqSettings.QueueName,
|
||||||
props.DeliveryMode = 2;
|
// durable: true,
|
||||||
//время жизни, мс
|
// exclusive: false,
|
||||||
//props.Expiration = "60000";
|
// autoDelete: false,
|
||||||
|
// arguments: args
|
||||||
|
// );
|
||||||
|
|
||||||
foreach (var msg in msgList)
|
// var props = channel.CreateBasicProperties();
|
||||||
{
|
// //храним на диске
|
||||||
var body = Encoding.UTF8.GetBytes(msg);
|
// props.DeliveryMode = 2;
|
||||||
channel.BasicPublish(exchange: "", routingKey: mqSettings.QueueName, basicProperties: props, body: body);
|
// //время жизни, мс
|
||||||
|
// //props.Expiration = "60000";
|
||||||
|
|
||||||
sendIdx++;
|
// foreach (var msg in msgList)
|
||||||
logger.LogDebug($"Отправлено сообщение в очередь: {mqSettings.HostName} {mqSettings.QueueName}, {msg}");
|
// {
|
||||||
}
|
// var body = Encoding.UTF8.GetBytes(msg);
|
||||||
}
|
// channel.BasicPublish(exchange: "", routingKey: mqSettings.QueueName, basicProperties: props, body: body);
|
||||||
|
|
||||||
return new MqSendResult { IsSuccess = true };
|
// sendIdx++;
|
||||||
}
|
// logger.LogDebug($"Отправлено сообщение в очередь: {mqSettings.HostName} {mqSettings.QueueName}, {msg}");
|
||||||
catch (Exception ex)
|
// }
|
||||||
{
|
// }
|
||||||
var notSendMsg = new List<string>();
|
|
||||||
|
|
||||||
// формируем список неотправленных элементов
|
// return new MqSendResult { IsSuccess = true };
|
||||||
for (int i = sendIdx; i < msgList.Length; i++)
|
//}
|
||||||
notSendMsg.Add(msgList[i]);
|
//catch (Exception ex)
|
||||||
|
//{
|
||||||
|
// var notSendMsg = new List<string>();
|
||||||
|
|
||||||
logger.LogError(ex, $"Ошибка при отправке сообщения в очередь {mqSettings.HostName} {mqSettings.QueueName}, {string.Join(',', notSendMsg)}");
|
// // формируем список неотправленных элементов
|
||||||
|
// for (int i = sendIdx; i < msgList.Length; i++)
|
||||||
|
// notSendMsg.Add(msgList[i]);
|
||||||
|
|
||||||
return new MqSendResult { IsSuccess = false, NotSendMessages = notSendMsg.ToArray() };
|
// logger.LogError(ex, $"Ошибка при отправке сообщения в очередь {mqSettings.HostName} {mqSettings.QueueName}, {string.Join(',', notSendMsg)}");
|
||||||
}
|
|
||||||
|
// return new MqSendResult { IsSuccess = false, NotSendMessages = notSendMsg.ToArray() };
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InitConsumer(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler)
|
public bool InitConsumer(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Устанавливаю соединение с RabbitMQ: {mqSettings.HostName}, {mqSettings.QueueName}");
|
logger.LogInformation($"Устанавливаю соединение с RabbitMQ: {mqSettings.HostName}, {mqSettings.QueueName}");
|
||||||
|
|
||||||
var facory = new ConnectionFactory
|
|
||||||
{
|
|
||||||
HostName = mqSettings.HostName,
|
|
||||||
UserName = mqSettings.User,
|
|
||||||
Password = mqSettings.Password,
|
|
||||||
AutomaticRecoveryEnabled = true,
|
|
||||||
DispatchConsumersAsync = true
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//using var connection = facory.CreateConnection();
|
|
||||||
//using var channel = connection.CreateModel();
|
|
||||||
|
|
||||||
connection = facory.CreateConnection();
|
|
||||||
channel = connection.CreateModel();
|
|
||||||
|
|
||||||
var args = new Dictionary<string, object> { { "x-queue-mode", "lazy" } };
|
|
||||||
|
|
||||||
channel.QueueDeclare(
|
|
||||||
queue: mqSettings.QueueName,
|
|
||||||
durable: true,
|
|
||||||
exclusive: false,
|
|
||||||
autoDelete: false,
|
|
||||||
arguments: args
|
|
||||||
);
|
|
||||||
|
|
||||||
logger.LogInformation($"Соединение с RabbitMQ установлено: {mqSettings.HostName}, {mqSettings.QueueName}");
|
|
||||||
|
|
||||||
channel.CallbackException += (ch, ea) =>
|
|
||||||
{
|
|
||||||
var _channel = (IModel?)ch;
|
|
||||||
// может тут если канал упал переоткрывать его
|
|
||||||
logger.LogError(ea.Exception, $"Ошибка при обработке очереди MqService сообщений из очереди. Канал открыт: {_channel?.IsOpen}");
|
|
||||||
};
|
|
||||||
|
|
||||||
var consumer = new AsyncEventingBasicConsumer(channel);
|
|
||||||
consumer.Received += async (ch, ea) =>
|
|
||||||
{
|
|
||||||
var content = Encoding.UTF8.GetString(ea.Body.ToArray());
|
|
||||||
logger.LogDebug($"Получено сообщение: {content}");
|
|
||||||
|
|
||||||
await messageHandler.Invoke(content);
|
|
||||||
|
|
||||||
channel.BasicAck(ea.DeliveryTag, false);
|
|
||||||
await Task.Yield();
|
|
||||||
};
|
|
||||||
|
|
||||||
string consumerTag = channel.BasicConsume(mqSettings.QueueName, false, consumer);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
logger.LogError(ex, $"Ошибка при получении сообщений из очереди: {mqSettings.HostName}, {mqSettings.QueueName}");
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
//var facory = new ConnectionFactory
|
||||||
|
//{
|
||||||
|
// HostName = mqSettings.HostName,
|
||||||
|
// UserName = mqSettings.User,
|
||||||
|
// Password = mqSettings.Password,
|
||||||
|
// AutomaticRecoveryEnabled = true,
|
||||||
|
// DispatchConsumersAsync = true
|
||||||
|
//};
|
||||||
|
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
// //using var connection = facory.CreateConnection();
|
||||||
|
// //using var channel = connection.CreateModel();
|
||||||
|
|
||||||
|
// connection = facory.CreateConnection();
|
||||||
|
// channel = connection.CreateModel();
|
||||||
|
|
||||||
|
// var args = new Dictionary<string, object> { { "x-queue-mode", "lazy" } };
|
||||||
|
|
||||||
|
// channel.QueueDeclare(
|
||||||
|
// queue: mqSettings.QueueName,
|
||||||
|
// durable: true,
|
||||||
|
// exclusive: false,
|
||||||
|
// autoDelete: false,
|
||||||
|
// arguments: args
|
||||||
|
// );
|
||||||
|
|
||||||
|
// logger.LogInformation($"Соединение с RabbitMQ установлено: {mqSettings.HostName}, {mqSettings.QueueName}");
|
||||||
|
|
||||||
|
// channel.CallbackException += (ch, ea) =>
|
||||||
|
// {
|
||||||
|
// var _channel = (IModel?)ch;
|
||||||
|
// // может тут если канал упал переоткрывать его
|
||||||
|
// logger.LogError(ea.Exception, $"Ошибка при обработке очереди MqService сообщений из очереди. Канал открыт: {_channel?.IsOpen}");
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var consumer = new AsyncEventingBasicConsumer(channel);
|
||||||
|
// consumer.Received += async (ch, ea) =>
|
||||||
|
// {
|
||||||
|
// var content = Encoding.UTF8.GetString(ea.Body.ToArray());
|
||||||
|
// logger.LogDebug($"Получено сообщение: {content}");
|
||||||
|
|
||||||
|
// await messageHandler.Invoke(content);
|
||||||
|
|
||||||
|
// channel.BasicAck(ea.DeliveryTag, false);
|
||||||
|
// await Task.Yield();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// string consumerTag = channel.BasicConsume(mqSettings.QueueName, false, consumer);
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
//}
|
||||||
|
//catch (Exception ex)
|
||||||
|
//{
|
||||||
|
// logger.LogError(ex, $"Ошибка при получении сообщений из очереди: {mqSettings.HostName}, {mqSettings.QueueName}");
|
||||||
|
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
channel?.Close();
|
//channel?.Close();
|
||||||
connection?.Close();
|
//connection?.Close();
|
||||||
|
|
||||||
channel?.Dispose();
|
//channel?.Dispose();
|
||||||
connection?.Dispose();
|
//connection?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
203
PARR.BLL/Services/Implementations/MqServiceV2.cs
Normal file
203
PARR.BLL/Services/Implementations/MqServiceV2.cs
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using PARR.BLL.Contracts.Interfaces;
|
||||||
|
using PARR.BLL.Domain.Mq;
|
||||||
|
using PARR.BLL.Services.Interfaces;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using RabbitMQ.Client.Events;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace PARR.BLL.Services.Implementations
|
||||||
|
{
|
||||||
|
internal class MqServiceV2 : IMqService
|
||||||
|
{
|
||||||
|
private readonly ILogger<MqServiceV2> logger;
|
||||||
|
|
||||||
|
private IConnection? consumerConnection;
|
||||||
|
private IChannel? consumerChannel;
|
||||||
|
|
||||||
|
// реализация для RabbitMQ.Client 7.1.2
|
||||||
|
|
||||||
|
public MqServiceV2(ILogger<MqServiceV2> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<bool> InitConsumerAsync(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"Устанавливаю соединение с RabbitMQ: {mqSettings.HostName}, {mqSettings.QueueName}");
|
||||||
|
|
||||||
|
var factory = new ConnectionFactory
|
||||||
|
{
|
||||||
|
HostName = mqSettings.HostName,
|
||||||
|
UserName = mqSettings.User,
|
||||||
|
Password = mqSettings.Password,
|
||||||
|
AutomaticRecoveryEnabled = true
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
consumerConnection = await factory.CreateConnectionAsync();
|
||||||
|
consumerChannel = await consumerConnection.CreateChannelAsync();
|
||||||
|
|
||||||
|
// кол-во сообщений которые можно обрабатывать за раз
|
||||||
|
if (mqSettings.PrefetchCount.HasValue)
|
||||||
|
{
|
||||||
|
await consumerChannel.BasicQosAsync(0, mqSettings.PrefetchCount.Value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// создаем очередь, вдруг ее еще нет
|
||||||
|
await QueueDeclareAsync(consumerChannel, mqSettings);
|
||||||
|
|
||||||
|
//await consumerChannel.QueueBindAsync(mqSettings.QueueName, "default", "routingKey");
|
||||||
|
|
||||||
|
|
||||||
|
consumerChannel.CallbackExceptionAsync += async (ch, ea) =>
|
||||||
|
{
|
||||||
|
var _channel = (IChannel?)ch;
|
||||||
|
// может тут если канал упал переоткрывать его
|
||||||
|
|
||||||
|
logger.LogError(ea.Exception, $"Ошибка при обработке очереди MqService сообщений из очереди. Канал открыт?: {_channel?.IsOpen}");
|
||||||
|
|
||||||
|
//if (consumerChannel.IsClosed)
|
||||||
|
//{
|
||||||
|
// //todo: этот момент проверить, успешно ли он переоткроет канал и очередь будет дальше обрабатываться
|
||||||
|
// await consumerChannel.CloseAsync();
|
||||||
|
// consumerChannel = await consumerConnection.CreateChannelAsync();
|
||||||
|
|
||||||
|
// logger.LogInformation(ea.Exception, $"Переоткрыл канал RabbitMq.");
|
||||||
|
//}
|
||||||
|
};
|
||||||
|
|
||||||
|
var consumer = new AsyncEventingBasicConsumer(consumerChannel);
|
||||||
|
//consumer.HandleChannelShutdownAsync = async (c, ea) =>{ };
|
||||||
|
|
||||||
|
consumer.ReceivedAsync += async (ch, ea) =>
|
||||||
|
{
|
||||||
|
var content = Encoding.UTF8.GetString(ea.Body.ToArray());
|
||||||
|
logger.LogDebug($"Получено сообщение: {content}");
|
||||||
|
|
||||||
|
await messageHandler.Invoke(content);
|
||||||
|
|
||||||
|
await consumerChannel.BasicAckAsync(ea.DeliveryTag, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
var consumerTag = await consumerChannel.BasicConsumeAsync(mqSettings.QueueName, false, consumer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, $"Ошибка при получении сообщений из очереди: {mqSettings.HostName}, {mqSettings.QueueName}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<MqSendResult> SendAsync(IMqSettings mqSettings, string[] msgList)
|
||||||
|
{
|
||||||
|
var factory = new ConnectionFactory
|
||||||
|
{
|
||||||
|
HostName = mqSettings.HostName,
|
||||||
|
UserName = mqSettings.User,
|
||||||
|
Password = mqSettings.Password,
|
||||||
|
AutomaticRecoveryEnabled = true
|
||||||
|
};
|
||||||
|
|
||||||
|
// индекс текущей отправки в очередь из массива msgList
|
||||||
|
// нужен для формирования списка неотправленных сообщений
|
||||||
|
var sendIdx = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var connection = await factory.CreateConnectionAsync())
|
||||||
|
using (var channel = await connection.CreateChannelAsync())
|
||||||
|
{
|
||||||
|
// создаем очередь, вдруг ее еще нет
|
||||||
|
await QueueDeclareAsync(channel, mqSettings);
|
||||||
|
|
||||||
|
var props = new BasicProperties();
|
||||||
|
//храним на диске
|
||||||
|
props.DeliveryMode = DeliveryModes.Persistent;
|
||||||
|
//время жизни, мс
|
||||||
|
props.Expiration = "60000";
|
||||||
|
props.ContentType = "text/plain";//"application/json";
|
||||||
|
|
||||||
|
foreach (var msg in msgList)
|
||||||
|
{
|
||||||
|
var body = Encoding.UTF8.GetBytes(msg);
|
||||||
|
await channel.BasicPublishAsync(
|
||||||
|
exchange: "",
|
||||||
|
routingKey: mqSettings.QueueName,
|
||||||
|
//TODO: проверить mandatory: true, может указать его в false
|
||||||
|
mandatory: true,
|
||||||
|
basicProperties: props,
|
||||||
|
body: body
|
||||||
|
);
|
||||||
|
|
||||||
|
sendIdx++;
|
||||||
|
logger.LogDebug($"Отправлено сообщение в очередь: {mqSettings.HostName} {mqSettings.QueueName}, {msg}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MqSendResult { IsSuccess = true };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var notSendMsg = new List<string>();
|
||||||
|
|
||||||
|
// формируем список неотправленных элементов
|
||||||
|
for (int i = sendIdx; i < msgList.Length; i++)
|
||||||
|
notSendMsg.Add(msgList[i]);
|
||||||
|
|
||||||
|
logger.LogError(ex, $"Ошибка при отправке сообщения в очередь {mqSettings.HostName} {mqSettings.QueueName}, {string.Join(',', notSendMsg)}");
|
||||||
|
|
||||||
|
return new MqSendResult { IsSuccess = false, NotSendMessages = notSendMsg.ToArray() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task QueueDeclareAsync(IChannel channel, IMqSettings mqSettings)
|
||||||
|
{
|
||||||
|
//https://www.rabbitmq.com/lazy-queues.html
|
||||||
|
// lazy - ленивой очереди больше нет
|
||||||
|
var args = new Dictionary<string, object?> { { "x-queue-mode", "lazy" } };
|
||||||
|
|
||||||
|
//Объявляем очередь с которой будем работать.
|
||||||
|
//Если такой очереди ещё нет, то создатся.
|
||||||
|
//Если нет, нужно параметры типа durable должны совпадать иначе будет ошибка.
|
||||||
|
//В целом эти параметры можно посмотреть в админке RabbitMQ
|
||||||
|
await channel.QueueDeclareAsync(
|
||||||
|
queue: mqSettings.QueueName,
|
||||||
|
durable: true,
|
||||||
|
exclusive: false,
|
||||||
|
autoDelete: false,
|
||||||
|
arguments: args
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (consumerChannel != null)
|
||||||
|
{
|
||||||
|
if (consumerChannel.IsOpen)
|
||||||
|
{
|
||||||
|
await consumerChannel.CloseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
await consumerChannel.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (consumerConnection != null)
|
||||||
|
{
|
||||||
|
if (consumerConnection.IsOpen)
|
||||||
|
{
|
||||||
|
await consumerConnection.CloseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
await consumerConnection.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ namespace PARR.BLL.Services.Interfaces
|
|||||||
{
|
{
|
||||||
public delegate Task MqMessageHandlerDelegate(string msg);
|
public delegate Task MqMessageHandlerDelegate(string msg);
|
||||||
|
|
||||||
public interface IMqService : IDisposable
|
public interface IMqService : IAsyncDisposable // IDisposable
|
||||||
{
|
{
|
||||||
bool InitConsumer(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler);
|
Task<bool> InitConsumerAsync(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler);
|
||||||
MqSendResult Send(IMqSettings mqSettings, string[] msgList);
|
Task<MqSendResult> SendAsync(IMqSettings mqSettings, string[] msgList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using PARR.DAL.Models;
|
|||||||
using PARR.DAL.Services.Interfaces;
|
using PARR.DAL.Services.Interfaces;
|
||||||
using PARR.EsppOrderManager.Services;
|
using PARR.EsppOrderManager.Services;
|
||||||
using PARR.EsppOrderManager.Settings;
|
using PARR.EsppOrderManager.Settings;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PARR.EsppOrderManager
|
namespace PARR.EsppOrderManager
|
||||||
{
|
{
|
||||||
@@ -40,11 +41,11 @@ namespace PARR.EsppOrderManager
|
|||||||
this.resultTemplateSettings = resultTemplateSettings;
|
this.resultTemplateSettings = resultTemplateSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
// логика работы описана в документации
|
// логика работы описана в документации
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, ManageOrderAsync);
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, ManageOrderAsync);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
@@ -53,9 +54,9 @@ namespace PARR.EsppOrderManager
|
|||||||
//await ManageOrderAsync("{\"OrderId\":\"49191af5-c313-4388-9720-a61fd13f15a8\"}");
|
//await ManageOrderAsync("{\"OrderId\":\"49191af5-c313-4388-9720-a61fd13f15a8\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IEsppOrderManager
|
public interface IEsppOrderManager
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.EsppOrderManager.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ namespace PARR.EsppOrderManagerWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
esppOrderManager.Start();
|
await esppOrderManager.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
esppOrderManager.Stop();
|
esppOrderManager.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IScheduleSyncher
|
public interface IScheduleSyncher
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace PARR.EsppScheduleSync
|
|||||||
private readonly ISyncService<EsppObjectSchedule> syncService;
|
private readonly ISyncService<EsppObjectSchedule> syncService;
|
||||||
private readonly SettingsFromDb settingsFromDb;
|
private readonly SettingsFromDb settingsFromDb;
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
private readonly INextRunModifierService nextRunModifierService;
|
//private readonly INextRunModifierService nextRunModifierService;
|
||||||
|
|
||||||
public ScheduleSyncher(
|
public ScheduleSyncher(
|
||||||
ILogger<ScheduleSyncher> logger,
|
ILogger<ScheduleSyncher> logger,
|
||||||
@@ -28,8 +28,8 @@ namespace PARR.EsppScheduleSync
|
|||||||
IMqService mqService,
|
IMqService mqService,
|
||||||
ISyncService<EsppObjectSchedule> syncService,
|
ISyncService<EsppObjectSchedule> syncService,
|
||||||
SettingsFromDb settingsFromDb,
|
SettingsFromDb settingsFromDb,
|
||||||
IServiceProvider serviceProvider,
|
IServiceProvider serviceProvider
|
||||||
INextRunModifierService nextRunModifierService
|
//INextRunModifierService nextRunModifierService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@@ -38,7 +38,7 @@ namespace PARR.EsppScheduleSync
|
|||||||
this.syncService = syncService;
|
this.syncService = syncService;
|
||||||
this.settingsFromDb = settingsFromDb;
|
this.settingsFromDb = settingsFromDb;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
this.nextRunModifierService = nextRunModifierService;
|
//this.nextRunModifierService = nextRunModifierService;
|
||||||
if (globalSettings.MqSettings == null)
|
if (globalSettings.MqSettings == null)
|
||||||
{
|
{
|
||||||
logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
|
logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
|
||||||
@@ -47,9 +47,9 @@ namespace PARR.EsppScheduleSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
var isConnected = mqService.InitConsumer(globalSettings!.MqSettings!, SyncScheduleAsync);
|
var isConnected = await mqService.InitConsumerAsync(globalSettings!.MqSettings!, SyncScheduleAsync);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
@@ -58,9 +58,9 @@ namespace PARR.EsppScheduleSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
|
|
||||||
logger.LogInformation($"=== === === Соединение с очередью {globalSettings.MqSettings!.QueueName} закрыто === === ===");
|
logger.LogInformation($"=== === === Соединение с очередью {globalSettings.MqSettings!.QueueName} закрыто === === ===");
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,19 @@ namespace PARR.EsppScheduleSync
|
|||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
private EsppObjectSchedule ConvertDbObjToEsppObj(Template template)
|
private EsppObjectSchedule ConvertDbObjToEsppObj(Template template)
|
||||||
{
|
{
|
||||||
|
//дефолтное значение, изменится в сервисе nextRunModifierService
|
||||||
|
var nextRunByAccountRobotTimeZone = DateTimeOffset.MinValue;
|
||||||
|
|
||||||
|
using (var scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var nextRunModifierService = scope.ServiceProvider.GetService<INextRunModifierService>();
|
||||||
|
if (nextRunModifierService == null)
|
||||||
|
throw new Exception($"Не найден сервис: {nameof(INextRunModifierService)}");
|
||||||
|
|
||||||
|
nextRunByAccountRobotTimeZone = nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var esppObjectFromDb = new EsppObjectSchedule
|
var esppObjectFromDb = new EsppObjectSchedule
|
||||||
{
|
{
|
||||||
TemplateName = template.Name,
|
TemplateName = template.Name,
|
||||||
@@ -92,8 +105,10 @@ namespace PARR.EsppScheduleSync
|
|||||||
//Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
|
//Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
|
||||||
TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "",
|
TypeV60calendar = settingsFromDb.ScheduleExclude == "Нет исключений" ? "NONE" : "",
|
||||||
//Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
|
//Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
|
||||||
Scheduled = EsppScheduleHelpers.GetNextRun(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
|
//Scheduled = EsppScheduleHelpers.GetNextRun(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
|
||||||
BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
|
//BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
|
||||||
|
Scheduled = EsppScheduleHelpers.GetNextRun(nextRunByAccountRobotTimeZone),
|
||||||
|
BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunByAccountRobotTimeZone),
|
||||||
Timezone = settingsFromDb.ScheduleTimezone,
|
Timezone = settingsFromDb.ScheduleTimezone,
|
||||||
//Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать
|
//Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать
|
||||||
TerminationType = settingsFromDb.ScheduleRepeatRange == "Отсутствует дата завершения" ? "forever" : "",
|
TerminationType = settingsFromDb.ScheduleRepeatRange == "Отсутствует дата завершения" ? "forever" : "",
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ namespace PARR.EsppScheduleSync.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using PARR.DAL.TransformServices;
|
|
||||||
using PARR.EsppScheduleSync;
|
using PARR.EsppScheduleSync;
|
||||||
|
|
||||||
namespace PARR.EsppScheduleSyncWorker
|
namespace PARR.EsppScheduleSyncWorker
|
||||||
@@ -16,12 +15,12 @@ namespace PARR.EsppScheduleSyncWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
scheduleSyncher.Start();
|
await scheduleSyncher.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
scheduleSyncher.Stop();
|
scheduleSyncher.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"HostName": "parr-rabbitmq",
|
"HostName": "parr-rabbitmq",
|
||||||
"QueueName": "parr-espp-schedulers",
|
"QueueName": "parr-espp-schedulers",
|
||||||
"User": "espp_schedulers_reader",
|
"User": "espp_schedulers_reader",
|
||||||
"Password": "KjdhGLJDshgd&^%84S2"
|
"Password": "KjdhGLJDshgd&^%84S2",
|
||||||
|
"PrefetchCount": 100
|
||||||
},
|
},
|
||||||
"ParsingSeparator": "<|>"
|
"ParsingSeparator": "<|>"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,21 +12,25 @@ namespace PARR.EsppSync
|
|||||||
internal class SyncService<EsppObject> : ISyncService<EsppObject> where EsppObject : class, IEsppObject
|
internal class SyncService<EsppObject> : ISyncService<EsppObject> where EsppObject : class, IEsppObject
|
||||||
{
|
{
|
||||||
private readonly ILogger<SyncService<EsppObject>> logger;
|
private readonly ILogger<SyncService<EsppObject>> logger;
|
||||||
private readonly ITemplateService templateService;
|
private readonly IServiceProvider serviceProvider;
|
||||||
private readonly IRobotConfigurationService robotConfigurationService;
|
|
||||||
private readonly IShortcodesService shortcodesService;
|
//private readonly ITemplateService templateService;
|
||||||
|
//private readonly IRobotConfigurationService robotConfigurationService;
|
||||||
|
//private readonly IShortcodesService shortcodesService;
|
||||||
|
|
||||||
public SyncService(
|
public SyncService(
|
||||||
ILogger<SyncService<EsppObject>> logger,
|
ILogger<SyncService<EsppObject>> logger,
|
||||||
ITemplateService templateService,
|
IServiceProvider serviceProvider
|
||||||
IRobotConfigurationService robotConfigurationService,
|
//ITemplateService templateService,
|
||||||
IShortcodesService shortcodesService
|
//IRobotConfigurationService robotConfigurationService,
|
||||||
|
//IShortcodesService shortcodesService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.templateService = templateService;
|
this.serviceProvider = serviceProvider;
|
||||||
this.robotConfigurationService = robotConfigurationService;
|
//this.templateService = templateService;
|
||||||
this.shortcodesService = shortcodesService;
|
//this.robotConfigurationService = robotConfigurationService;
|
||||||
|
//this.shortcodesService = shortcodesService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +56,13 @@ namespace PARR.EsppSync
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (var scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var templateService = GetServiceInScope<ITemplateService>(scope);
|
||||||
|
var robotConfigurationService = GetServiceInScope<IRobotConfigurationService>(scope);
|
||||||
|
var shortcodesService = GetServiceInScope<IShortcodesService>(scope);
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var template = await templateService.GetTemplateByNameAsync(esppObject.TemplateName);
|
var template = await templateService.GetTemplateByNameAsync(esppObject.TemplateName);
|
||||||
@@ -154,6 +165,7 @@ namespace PARR.EsppSync
|
|||||||
logger.LogError(ex, $"Ошибка синхронизации объекта АСУ ЕСПП {esppObject.TemplateName}");
|
logger.LogError(ex, $"Ошибка синхронизации объекта АСУ ЕСПП {esppObject.TemplateName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SetUpdateStatus(ref Template template, IRobotConfigurationService robotConfigurationService, RobotsEnum robot)
|
private void SetUpdateStatus(ref Template template, IRobotConfigurationService robotConfigurationService, RobotsEnum robot)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface ITemplateSyncer
|
public interface ITemplateSyncer
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace PARR.EsppTemplateSync.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StorageSettings
|
internal class StorageSettings
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace PARR.EsppTemplateSync
|
|||||||
filterExtensions = string.Join(",", storageSettings.EsppTemplates!.AllowedExtensions).Replace(".", "*.");
|
filterExtensions = string.Join(",", storageSettings.EsppTemplates!.AllowedExtensions).Replace(".", "*.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void StartAsync()
|
||||||
{
|
{
|
||||||
//смотрим, доступна ли папка
|
//смотрим, доступна ли папка
|
||||||
if (!Directory.Exists(dirPath))
|
if (!Directory.Exists(dirPath))
|
||||||
@@ -80,7 +80,7 @@ namespace PARR.EsppTemplateSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Stop()
|
public void StopAsync()
|
||||||
{
|
{
|
||||||
//watcher?.Dispose();
|
//watcher?.Dispose();
|
||||||
logger.LogInformation($"=== === === FileWatcher остановлен === === ===");
|
logger.LogInformation($"=== === === FileWatcher остановлен === === ===");
|
||||||
@@ -132,5 +132,14 @@ namespace PARR.EsppTemplateSync
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task ITemplateSyncer.StartAsync()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITemplateSyncer.StopAsync()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,21 +15,25 @@ namespace PARR.EsppTemplateSync
|
|||||||
private readonly GlobalSettings globalSettings;
|
private readonly GlobalSettings globalSettings;
|
||||||
private readonly IMqService mqService;
|
private readonly IMqService mqService;
|
||||||
private readonly SettingsFromDb settingsFromDb;
|
private readonly SettingsFromDb settingsFromDb;
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly ISyncService<EsppObjectTemplate> syncService;
|
||||||
|
|
||||||
|
//private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
public TemplateMQSyncer(
|
public TemplateMQSyncer(
|
||||||
ILogger<TemplateMQSyncer> logger,
|
ILogger<TemplateMQSyncer> logger,
|
||||||
GlobalSettings globalSettings,
|
GlobalSettings globalSettings,
|
||||||
IMqService mqService,
|
IMqService mqService,
|
||||||
SettingsFromDb settingsFromDb,
|
SettingsFromDb settingsFromDb,
|
||||||
IServiceProvider serviceProvider
|
ISyncService<EsppObjectTemplate> syncService
|
||||||
|
//IServiceProvider serviceProvider
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.globalSettings = globalSettings;
|
this.globalSettings = globalSettings;
|
||||||
this.mqService = mqService;
|
this.mqService = mqService;
|
||||||
this.settingsFromDb = settingsFromDb;
|
this.settingsFromDb = settingsFromDb;
|
||||||
this.serviceProvider = serviceProvider;
|
this.syncService = syncService;
|
||||||
|
//this.serviceProvider = serviceProvider;
|
||||||
if (globalSettings.MqSettings == null)
|
if (globalSettings.MqSettings == null)
|
||||||
{
|
{
|
||||||
logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
|
logger.LogError("Нет секции настроек хранилища. MqSettings, EsppTemplates");
|
||||||
@@ -37,10 +41,10 @@ namespace PARR.EsppTemplateSync
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(globalSettings!.MqSettings!, SyncTemplateAsync);
|
var isConnected = await mqService.InitConsumerAsync(globalSettings!.MqSettings!, SyncTemplateAsync);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
@@ -48,9 +52,9 @@ namespace PARR.EsppTemplateSync
|
|||||||
logger.LogInformation($"Запущена проверка очереди {globalSettings.MqSettings!.QueueName}.");
|
logger.LogInformation($"Запущена проверка очереди {globalSettings.MqSettings!.QueueName}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
|
|
||||||
logger.LogInformation($"=== === === Соединение с очередью {globalSettings.MqSettings!.QueueName} закрыто === === ===");
|
logger.LogInformation($"=== === === Соединение с очередью {globalSettings.MqSettings!.QueueName} закрыто === === ===");
|
||||||
}
|
}
|
||||||
@@ -58,15 +62,15 @@ namespace PARR.EsppTemplateSync
|
|||||||
|
|
||||||
private async Task SyncTemplateAsync(string str)
|
private async Task SyncTemplateAsync(string str)
|
||||||
{
|
{
|
||||||
using (var scope = serviceProvider.CreateScope())
|
//using (var scope = serviceProvider.CreateScope())
|
||||||
{
|
//{
|
||||||
var syncService = scope.ServiceProvider.GetService<ISyncService<EsppObjectTemplate>>();
|
// var syncService = scope.ServiceProvider.GetService<ISyncService<EsppObjectTemplate>>();
|
||||||
|
|
||||||
if (syncService == null)
|
// if (syncService == null)
|
||||||
throw new Exception($"Не смог получить серивс {nameof(ITemplateSyncer)}");
|
// throw new Exception($"Не смог получить серивс {nameof(ITemplateSyncer)}");
|
||||||
|
|
||||||
await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObj);
|
await syncService.SyncEsppObjectAsync(str, ParseStrToEsppObject, ConvertDbObjToEsppObj);
|
||||||
}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ namespace PARR.EsppTemplateSyncWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
templateSyncer.Start();
|
await templateSyncer.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
templateSyncer.Stop();
|
templateSyncer.StopAsync().Wait();
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,8 @@
|
|||||||
"HostName": "parr-rabbitmq",
|
"HostName": "parr-rabbitmq",
|
||||||
"QueueName": "parr-espp-templates",
|
"QueueName": "parr-espp-templates",
|
||||||
"User": "espp_templates_reader",
|
"User": "espp_templates_reader",
|
||||||
"Password": "P@ssReaderPtk202!"
|
"Password": "P@ssReaderPtk202!",
|
||||||
|
"PrefetchCount": 100
|
||||||
},
|
},
|
||||||
"StorageSettings": {
|
"StorageSettings": {
|
||||||
"CheckIntervalSeconds": 30
|
"CheckIntervalSeconds": 30
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using PARR.BLL.Services.Interfaces;
|
|||||||
using PARR.DAL.Models;
|
using PARR.DAL.Models;
|
||||||
using PARR.GeneratorTemplates.Services;
|
using PARR.GeneratorTemplates.Services;
|
||||||
using PARR.GeneratorTemplates.Settings;
|
using PARR.GeneratorTemplates.Settings;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PARR.GeneratorTemplates
|
namespace PARR.GeneratorTemplates
|
||||||
{
|
{
|
||||||
@@ -35,7 +36,7 @@ namespace PARR.GeneratorTemplates
|
|||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
#region test
|
#region test
|
||||||
// string msg = "{\"WorkId\":\"91219bec-e5f7-4a1a-b4c9-c135035d2498\",\"ApplicationId\":\"13044a1f-fa0c-476f-b501-2b8d06bac9f8\",\"Action\":\"create\",\"Ek\":\"ВРТ*ДВС\",\"StatusEk\":0}";
|
// string msg = "{\"WorkId\":\"91219bec-e5f7-4a1a-b4c9-c135035d2498\",\"ApplicationId\":\"13044a1f-fa0c-476f-b501-2b8d06bac9f8\",\"Action\":\"create\",\"Ek\":\"ВРТ*ДВС\",\"StatusEk\":0}";
|
||||||
@@ -44,15 +45,15 @@ namespace PARR.GeneratorTemplates
|
|||||||
// await GenerateTemplates(msg);
|
// await GenerateTemplates(msg);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, GenerateTemplates);
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, GenerateTemplates);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IGeneratorTemplate
|
public interface IGeneratorTemplate
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.GeneratorTemplates.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace PARR.GeneratorTemplatesWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
generatorTemplate.Start();
|
await generatorTemplate.StartAsync();
|
||||||
//while (!stoppingToken.IsCancellationRequested)
|
//while (!stoppingToken.IsCancellationRequested)
|
||||||
//{
|
//{
|
||||||
// _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
|
// _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
|
||||||
@@ -25,7 +25,7 @@ namespace PARR.GeneratorTemplatesWorker
|
|||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
generatorTemplate.Stop();
|
generatorTemplate.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ namespace PARR.JobAutoControl
|
|||||||
{
|
{
|
||||||
job.JobEkMasks.ToList().ForEach(ek =>
|
job.JobEkMasks.ToList().ForEach(ek =>
|
||||||
{
|
{
|
||||||
job.JobAutoControlInEkStatuses.ToList().ForEach(ekStatus =>
|
//todo: проверить, нормально ли отрабатывает async в Foreach
|
||||||
|
job.JobAutoControlInEkStatuses.ToList().ForEach(async ekStatus =>
|
||||||
{
|
{
|
||||||
var request = new GeneratorTemplateMq
|
var request = new GeneratorTemplateMq
|
||||||
{
|
{
|
||||||
@@ -103,7 +104,7 @@ namespace PARR.JobAutoControl
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(request);
|
var msg = JsonSerializer.Serialize(request);
|
||||||
|
|
||||||
var result = mqService.Send(mqSettings.Generator, new[] { msg });
|
var result =await mqService.SendAsync(mqSettings.Generator, new[] { msg });
|
||||||
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
logger.LogInformation($"Отправлен запрос на генерацию: {msg}");
|
logger.LogInformation($"Отправлен запрос на генерацию: {msg}");
|
||||||
@@ -135,7 +136,8 @@ namespace PARR.JobAutoControl
|
|||||||
if (!jobsToDeactivate.Any())
|
if (!jobsToDeactivate.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
jobsToDeactivate.ForEach(applicationInWorkId =>
|
//todo: проверить, нормально ли отрабатывает async в foreach
|
||||||
|
jobsToDeactivate.ForEach(async applicationInWorkId =>
|
||||||
{
|
{
|
||||||
var request = new TemplateActivatorMq
|
var request = new TemplateActivatorMq
|
||||||
{
|
{
|
||||||
@@ -146,7 +148,7 @@ namespace PARR.JobAutoControl
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(request);
|
var msg = JsonSerializer.Serialize(request);
|
||||||
|
|
||||||
var result = mqService.Send(mqSettings.Activator, new[] { msg });
|
var result = await mqService.SendAsync(mqSettings.Activator, new[] { msg });
|
||||||
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
logger.LogInformation($"Отправлен запрос на деактивацию: {msg}");
|
logger.LogInformation($"Отправлен запрос на деактивацию: {msg}");
|
||||||
@@ -174,7 +176,8 @@ namespace PARR.JobAutoControl
|
|||||||
if (!jobsToActivate.Any())
|
if (!jobsToActivate.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
jobsToActivate.ForEach(applicationInWorkId =>
|
//todo: проверить, нормально ли отрабатывает async в foreach
|
||||||
|
jobsToActivate.ForEach(async applicationInWorkId =>
|
||||||
{
|
{
|
||||||
var request = new TemplateActivatorMq
|
var request = new TemplateActivatorMq
|
||||||
{
|
{
|
||||||
@@ -185,7 +188,7 @@ namespace PARR.JobAutoControl
|
|||||||
|
|
||||||
var msg = JsonSerializer.Serialize(request);
|
var msg = JsonSerializer.Serialize(request);
|
||||||
|
|
||||||
var result = mqService.Send(mqSettings.Activator, new[] { msg });
|
var result = await mqService.SendAsync(mqSettings.Activator, new[] { msg });
|
||||||
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
logger.LogInformation($"Отправлен запрос на активацию: {msg}");
|
logger.LogInformation($"Отправлен запрос на активацию: {msg}");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace PARR.JobAutoControl.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Activator : IMqSettings
|
internal class Activator : IMqSettings
|
||||||
@@ -22,6 +23,7 @@ namespace PARR.JobAutoControl.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace PARR.Master.Services
|
|||||||
|
|
||||||
if (objs.Any())
|
if (objs.Any())
|
||||||
{
|
{
|
||||||
var sendResult = mqService.Send(mqSettings, objs.ToArray());
|
var sendResult = await mqService.SendAsync(mqSettings, objs.ToArray());
|
||||||
if (sendResult.IsSuccess)
|
if (sendResult.IsSuccess)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Наряды переданы в RabbitMQ: {objs.Count()}");
|
logger.LogInformation($"Наряды переданы в RabbitMQ: {objs.Count()}");
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.Master.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,44 +6,45 @@ namespace PARR.MockData
|
|||||||
{
|
{
|
||||||
internal class EsppDataImporter
|
internal class EsppDataImporter
|
||||||
{
|
{
|
||||||
public void Import() {
|
public void Import()
|
||||||
var factory = new ConnectionFactory() { HostName = "10.99.253.216" };
|
|
||||||
factory.UserName = "espp_templates_robot";
|
|
||||||
factory.Password = "P@ssRwEsppTempl202";
|
|
||||||
|
|
||||||
string[] rows = EsppExport.data.Replace("\r", "").Split('\n');
|
|
||||||
using (var connection = factory.CreateConnection())
|
|
||||||
using (var channel = connection.CreateModel())
|
|
||||||
{
|
{
|
||||||
//https://www.rabbitmq.com/lazy-queues.html
|
//var factory = new ConnectionFactory() { HostName = "10.99.253.216" };
|
||||||
//Рекомендовано при работе порциями использовать ленивые очереди. сообщения не используют память
|
//factory.UserName = "espp_templates_robot";
|
||||||
//Формируем соответствующий аргумент
|
//factory.Password = "P@ssRwEsppTempl202";
|
||||||
Dictionary<String, Object> argums = new Dictionary<String, Object>();
|
|
||||||
argums.Add("x-queue-mode", "lazy");
|
|
||||||
|
|
||||||
//Объявляем очередь с которой будем работать. Если такой очереди ещё нет, то создатся. Если нет, нужно параметры типа durable должны совпадать иначе будет ошибка. В целом эти параметры можно посмотреть в админке RabbitMQ
|
//string[] rows = EsppExport.data.Replace("\r", "").Split('\n');
|
||||||
channel.QueueDeclare(queue: "parr-espp-templates",
|
//using (var connection = factory.CreateConnection())
|
||||||
durable: true,//If you want to make sure your messages are persisted, you need to create a durable queue. To do this, simply set the durable flag to true when creating the queue.
|
//using (var channel = connection.CreateModel())
|
||||||
exclusive: false,
|
//{
|
||||||
autoDelete: false,
|
// //https://www.rabbitmq.com/lazy-queues.html
|
||||||
arguments: argums);
|
// //Рекомендовано при работе порциями использовать ленивые очереди. сообщения не используют память
|
||||||
//перебираем строки и отправляем строки сообщениями
|
// //Формируем соответствующий аргумент
|
||||||
for (int i = 0; i < rows.Count(); i++)
|
// Dictionary<String, Object> argums = new Dictionary<String, Object>();
|
||||||
{
|
// argums.Add("x-queue-mode", "lazy");
|
||||||
var body = Encoding.UTF8.GetBytes(rows[i]);
|
|
||||||
IBasicProperties props = channel.CreateBasicProperties();
|
|
||||||
//If you don’t mark your messages as persistent, then RabbitMQ will store them in memory. This is fine if you’re just playing around or building a prototype. But if you’re building a production system, then you need to make sure that your messages are persisted to disk so that they’re not lost if the server crashes.
|
|
||||||
//Говорим менеджеру RabbitMq при получении хранить сообщения на диске
|
|
||||||
props.DeliveryMode = 2;
|
|
||||||
//время жизни в мс. на этапе отладки сделаем коротким чтобы не устраивать помойку
|
|
||||||
props.Expiration = "60000";
|
|
||||||
|
|
||||||
channel.BasicPublish(exchange: "",
|
// //Объявляем очередь с которой будем работать. Если такой очереди ещё нет, то создатся. Если нет, нужно параметры типа durable должны совпадать иначе будет ошибка. В целом эти параметры можно посмотреть в админке RabbitMQ
|
||||||
routingKey: "parr-espp-templates",//совпадает с именем очереди иначе не принимает
|
// channel.QueueDeclare(queue: "parr-espp-templates",
|
||||||
basicProperties: props,
|
// durable: true,//If you want to make sure your messages are persisted, you need to create a durable queue. To do this, simply set the durable flag to true when creating the queue.
|
||||||
body: body);
|
// exclusive: false,
|
||||||
}
|
// autoDelete: false,
|
||||||
}
|
// arguments: argums);
|
||||||
|
// //перебираем строки и отправляем строки сообщениями
|
||||||
|
// for (int i = 0; i < rows.Count(); i++)
|
||||||
|
// {
|
||||||
|
// var body = Encoding.UTF8.GetBytes(rows[i]);
|
||||||
|
// IBasicProperties props = channel.CreateBasicProperties();
|
||||||
|
// //If you don’t mark your messages as persistent, then RabbitMQ will store them in memory. This is fine if you’re just playing around or building a prototype. But if you’re building a production system, then you need to make sure that your messages are persisted to disk so that they’re not lost if the server crashes.
|
||||||
|
// //Говорим менеджеру RabbitMq при получении хранить сообщения на диске
|
||||||
|
// props.DeliveryMode = 2;
|
||||||
|
// //время жизни в мс. на этапе отладки сделаем коротким чтобы не устраивать помойку
|
||||||
|
// props.Expiration = "60000";
|
||||||
|
|
||||||
|
// channel.BasicPublish(exchange: "",
|
||||||
|
// routingKey: "parr-espp-templates",//совпадает с именем очереди иначе не принимает
|
||||||
|
// basicProperties: props,
|
||||||
|
// body: body);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
public interface IMqTemplateActivator
|
public interface IMqTemplateActivator
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using PARR.BLL.Domain.Mq;
|
using PARR.BLL.Domain.Mq;
|
||||||
using PARR.BLL.Services.Interfaces;
|
using PARR.BLL.Services.Interfaces;
|
||||||
using PARR.Constants;
|
using PARR.Constants;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PARR.TemplateActivator;
|
namespace PARR.TemplateActivator;
|
||||||
|
|
||||||
@@ -31,9 +32,9 @@ internal class MqTemplateActivator : IMqTemplateActivator
|
|||||||
this.validatorService = validatorService;
|
this.validatorService = validatorService;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, UpdateTemplateStatusAsync);
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, UpdateTemplateStatusAsync);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
@@ -64,8 +65,8 @@ internal class MqTemplateActivator : IMqTemplateActivator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ internal class MqSettings : IMqSettings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ namespace PARR.TemplateActivatorWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
mqTemplateActivator.Start();
|
await mqTemplateActivator.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
mqTemplateActivator.Stop();
|
mqTemplateActivator.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
public interface IMqTemplateDistributor
|
public interface IMqTemplateDistributor
|
||||||
{
|
{
|
||||||
void Start();
|
Task StartAsync();
|
||||||
void Stop();
|
Task StopAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using PARR.BLL.Domain.Mq;
|
|||||||
using PARR.BLL.Services.Interfaces;
|
using PARR.BLL.Services.Interfaces;
|
||||||
using PARR.TemplateDistributor.Services;
|
using PARR.TemplateDistributor.Services;
|
||||||
using PARR.TemplateDistributor.Settings;
|
using PARR.TemplateDistributor.Settings;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PARR.TemplateDistributor
|
namespace PARR.TemplateDistributor
|
||||||
{
|
{
|
||||||
@@ -31,18 +32,18 @@ namespace PARR.TemplateDistributor
|
|||||||
this.validatorService = validatorService;
|
this.validatorService = validatorService;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, UpdateScheduleAsync);
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, UpdateScheduleAsync);
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("Ошибка при подключении к RabbitMq");
|
throw new Exception("Ошибка при подключении к RabbitMq");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public async Task StopAsync()
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
await mqService.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateScheduleAsync(string msg)
|
private async Task UpdateScheduleAsync(string msg)
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ namespace PARR.TemplateDistributor.Settings
|
|||||||
public string QueueName { get; set; } = string.Empty;
|
public string QueueName { get; set; } = string.Empty;
|
||||||
public string User { get; set; } = string.Empty;
|
public string User { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public ushort? PrefetchCount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ namespace PARR.TemplateDistributorWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
mqTemplateDistributor.Start();
|
await mqTemplateDistributor.StartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
mqTemplateDistributor.Stop();
|
mqTemplateDistributor.StopAsync().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,19 +35,16 @@ namespace PARR.TemplateGeneratorWorker
|
|||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
var isConnected = await mqService.InitConsumerAsync(mqSettings, GenerateTemplateAsync);
|
||||||
{
|
|
||||||
var isConnected = mqService.InitConsumer(mqSettings, GenerateTemplateAsync);
|
|
||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
throw new Exception("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> RabbitMq");
|
throw new Exception("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> RabbitMq");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
mqService.Dispose();
|
mqService.DisposeAsync().AsTask().Wait();
|
||||||
|
|
||||||
return base.StopAsync(cancellationToken);
|
return base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user