|
|
@ -5,6 +5,7 @@ using RabbitMQ.Client; |
|
|
using RabbitMQ.Client.Events; |
|
|
using RabbitMQ.Client.Events; |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Concurrent; |
|
|
using System.Collections.Concurrent; |
|
|
|
|
|
using System.Threading; |
|
|
using System.Threading.Tasks; |
|
|
using System.Threading.Tasks; |
|
|
using Volo.Abp.DependencyInjection; |
|
|
using Volo.Abp.DependencyInjection; |
|
|
using Volo.Abp.ExceptionHandling; |
|
|
using Volo.Abp.ExceptionHandling; |
|
|
@ -28,13 +29,13 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
|
|
|
|
|
|
protected string? ConnectionName { get; private set; } |
|
|
protected string? ConnectionName { get; private set; } |
|
|
|
|
|
|
|
|
protected ConcurrentBag<Func<IModel, BasicDeliverEventArgs, Task>> Callbacks { get; } |
|
|
protected ConcurrentBag<Func<IChannel, BasicDeliverEventArgs, Task>> Callbacks { get; } |
|
|
|
|
|
|
|
|
protected IModel? Channel { get; private set; } |
|
|
protected IChannel? Channel { get; private set; } |
|
|
|
|
|
|
|
|
protected ConcurrentQueue<QueueBindCommand> QueueBindCommands { get; } |
|
|
protected ConcurrentQueue<QueueBindCommand> QueueBindCommands { get; } |
|
|
|
|
|
|
|
|
protected object ChannelSendSyncLock { get; } = new object(); |
|
|
protected SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); |
|
|
|
|
|
|
|
|
public RabbitMqMessageConsumer( |
|
|
public RabbitMqMessageConsumer( |
|
|
IConnectionPool connectionPool, |
|
|
IConnectionPool connectionPool, |
|
|
@ -47,7 +48,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
Logger = NullLogger<RabbitMqMessageConsumer>.Instance; |
|
|
Logger = NullLogger<RabbitMqMessageConsumer>.Instance; |
|
|
|
|
|
|
|
|
QueueBindCommands = new ConcurrentQueue<QueueBindCommand>(); |
|
|
QueueBindCommands = new ConcurrentQueue<QueueBindCommand>(); |
|
|
Callbacks = new ConcurrentBag<Func<IModel, BasicDeliverEventArgs, Task>>(); |
|
|
Callbacks = new ConcurrentBag<Func<IChannel, BasicDeliverEventArgs, Task>>(); |
|
|
|
|
|
|
|
|
Timer.Period = 5000; //5 sec.
|
|
|
Timer.Period = 5000; //5 sec.
|
|
|
Timer.Elapsed = Timer_Elapsed; |
|
|
Timer.Elapsed = Timer_Elapsed; |
|
|
@ -88,21 +89,21 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
lock (ChannelSendSyncLock) |
|
|
using (await Semaphore.LockAsync()) |
|
|
{ |
|
|
{ |
|
|
if (QueueBindCommands.TryPeek(out var command)) |
|
|
if (QueueBindCommands.TryPeek(out var command)) |
|
|
{ |
|
|
{ |
|
|
switch (command.Type) |
|
|
switch (command.Type) |
|
|
{ |
|
|
{ |
|
|
case QueueBindType.Bind: |
|
|
case QueueBindType.Bind: |
|
|
Channel.QueueBind( |
|
|
await Channel.QueueBindAsync( |
|
|
queue: Queue.QueueName, |
|
|
queue: Queue.QueueName, |
|
|
exchange: Exchange.ExchangeName, |
|
|
exchange: Exchange.ExchangeName, |
|
|
routingKey: command.RoutingKey |
|
|
routingKey: command.RoutingKey |
|
|
); |
|
|
); |
|
|
break; |
|
|
break; |
|
|
case QueueBindType.Unbind: |
|
|
case QueueBindType.Unbind: |
|
|
Channel.QueueUnbind( |
|
|
await Channel.QueueUnbindAsync( |
|
|
queue: Queue.QueueName, |
|
|
queue: Queue.QueueName, |
|
|
exchange: Exchange.ExchangeName, |
|
|
exchange: Exchange.ExchangeName, |
|
|
routingKey: command.RoutingKey |
|
|
routingKey: command.RoutingKey |
|
|
@ -124,7 +125,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public virtual void OnMessageReceived(Func<IModel, BasicDeliverEventArgs, Task> callback) |
|
|
public virtual void OnMessageReceived(Func<IChannel, BasicDeliverEventArgs, Task> callback) |
|
|
{ |
|
|
{ |
|
|
Callbacks.Add(callback); |
|
|
Callbacks.Add(callback); |
|
|
} |
|
|
} |
|
|
@ -144,11 +145,11 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
|
|
|
|
|
|
try |
|
|
try |
|
|
{ |
|
|
{ |
|
|
Channel = ConnectionPool |
|
|
Channel = await (await ConnectionPool |
|
|
.Get(ConnectionName) |
|
|
.GetAsync(ConnectionName)) |
|
|
.CreateModel(); |
|
|
.CreateChannelAsync(); |
|
|
|
|
|
|
|
|
Channel.ExchangeDeclare( |
|
|
await Channel.ExchangeDeclareAsync( |
|
|
exchange: Exchange.ExchangeName, |
|
|
exchange: Exchange.ExchangeName, |
|
|
type: Exchange.Type, |
|
|
type: Exchange.Type, |
|
|
durable: Exchange.Durable, |
|
|
durable: Exchange.Durable, |
|
|
@ -156,7 +157,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
arguments: Exchange.Arguments |
|
|
arguments: Exchange.Arguments |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
Channel.QueueDeclare( |
|
|
await Channel.QueueDeclareAsync( |
|
|
queue: Queue.QueueName, |
|
|
queue: Queue.QueueName, |
|
|
durable: Queue.Durable, |
|
|
durable: Queue.Durable, |
|
|
exclusive: Queue.Exclusive, |
|
|
exclusive: Queue.Exclusive, |
|
|
@ -166,13 +167,13 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
|
|
|
|
|
|
if (Queue.PrefetchCount.HasValue) |
|
|
if (Queue.PrefetchCount.HasValue) |
|
|
{ |
|
|
{ |
|
|
Channel.BasicQos(0, Queue.PrefetchCount.Value, false); |
|
|
await Channel.BasicQosAsync(0, Queue.PrefetchCount.Value, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var consumer = new AsyncEventingBasicConsumer(Channel); |
|
|
var consumer = new AsyncEventingBasicConsumer(Channel); |
|
|
consumer.Received += HandleIncomingMessageAsync; |
|
|
consumer.ReceivedAsync += HandleIncomingMessageAsync; |
|
|
|
|
|
|
|
|
Channel.BasicConsume( |
|
|
await Channel.BasicConsumeAsync( |
|
|
queue: Queue.QueueName, |
|
|
queue: Queue.QueueName, |
|
|
autoAck: false, |
|
|
autoAck: false, |
|
|
consumer: consumer |
|
|
consumer: consumer |
|
|
@ -194,17 +195,23 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen |
|
|
await callback(Channel!, basicDeliverEventArgs); |
|
|
await callback(Channel!, basicDeliverEventArgs); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Channel?.BasicAck(basicDeliverEventArgs.DeliveryTag, multiple: false); |
|
|
if (Channel != null) |
|
|
|
|
|
{ |
|
|
|
|
|
await Channel.BasicAckAsync(basicDeliverEventArgs.DeliveryTag, multiple: false); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
catch (Exception ex) |
|
|
catch (Exception ex) |
|
|
{ |
|
|
{ |
|
|
try |
|
|
try |
|
|
{ |
|
|
{ |
|
|
Channel?.BasicNack( |
|
|
if (Channel != null) |
|
|
basicDeliverEventArgs.DeliveryTag, |
|
|
{ |
|
|
multiple: false, |
|
|
await Channel.BasicNackAsync( |
|
|
requeue: true |
|
|
basicDeliverEventArgs.DeliveryTag, |
|
|
); |
|
|
multiple: false, |
|
|
|
|
|
requeue: true |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
// ReSharper disable once EmptyGeneralCatchClause
|
|
|
// ReSharper disable once EmptyGeneralCatchClause
|
|
|
catch { } |
|
|
catch { } |
|
|
|