Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions samples/MerQure.Samples/DeadLetterExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ public async Task RunAsync()

// Get the consumer on the existing queue and consume its messages
var consumer = await _messagingService.GetConsumerAsync("deadletter.queue");
await consumer.ConsumeAsync((object sender, IMessagingEvent args) =>
await consumer.ConsumeAsync((object sender, MessagingEvent args) =>
{
var realDelay = DateTime.Now.Subtract(dateStart).TotalSeconds;
Console.WriteLine(string.Format("{0} received after {1:#.##}s.", args.Message.GetRoutingKey(), realDelay));
// send ACK: acknowlegdment to the queue
consumer.AcknowlegdeDeliveredMessageAsync(args);
return consumer.AcknowlegdeDeliveredMessageAsync(args).AsTask();
});
}
}
6 changes: 3 additions & 3 deletions samples/MerQure.Samples/SimpleExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@ public async Task RunAsync()
// Get the consumer on the existing queue and consume its messages
var consumer = await _messagingService.GetConsumerAsync("simple.queue");
var random = new Random();
await consumer.ConsumeAsync((object sender, IMessagingEvent args) =>
await consumer.ConsumeAsync((object sender, MessagingEvent args) =>
{
// we simulate the delivery success
if (random.Next() % 2 == 0)
{
Console.WriteLine("Retry " + args.Message.GetRoutingKey());
// send NACK: negative acknowlegdment to the queue
consumer.RejectDeliveredMessageAsync(args);
return consumer.RejectDeliveredMessageAsync(args).AsTask();
}
else
{
Console.WriteLine(args.Message.GetBody());
// send ACK: acknowlegdment to the queue
consumer.AcknowlegdeDeliveredMessageAsync(args);
return consumer.AcknowlegdeDeliveredMessageAsync(args).AsTask();
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion samples/MerQure.Samples/StopExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ await consumer.ConsumeAsync((_, args) =>
Thread.Sleep(10);
Console.WriteLine(args.Message.GetBody());
// send ACK: acknowlegdment to the queue
consumer.AcknowlegdeDeliveredMessageAsync(args);
return consumer.AcknowlegdeDeliveredMessageAsync(args).AsTask();
});

// Stop Consuming after 100 ms ~ 10 messages
Expand Down
33 changes: 19 additions & 14 deletions src/MerQure.RbMQ/Clients/Consumer.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using MerQure.Messages;
using MerQure.RbMQ.Content;
using MerQure.RbMQ.Events;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MerQure.RbMQ.Clients;
Expand All @@ -17,33 +17,37 @@ class Consumer : RabbitMqClient, IConsumer

private AsyncEventingBasicConsumer _consumer;
private readonly ushort _prefetchCount;
private readonly object _consumingLock;
private readonly SemaphoreSlim _consumingLock;

public Consumer(IChannel channel, string queueName, ushort prefetchCount)
: base(channel)
{
QueueName = queueName.ToLowerInvariant();
_prefetchCount = prefetchCount;
_consumingLock = new object();
_consumingLock = new SemaphoreSlim(1, 1);
}

public async Task ConsumeAsync(EventHandler<IMessagingEvent> onMessageReceived)
public async Task ConsumeAsync(AsyncEventHandler<MessagingEvent> onMessageReceived)
{
await Channel.BasicQosAsync(0, _prefetchCount, false);

_consumer = new AsyncEventingBasicConsumer(Channel);
_consumer.ReceivedAsync += (sender, args) =>
_consumer.ReceivedAsync += async (sender, args) =>
{
if (onMessageReceived != null)
{
lock (_consumingLock)
await _consumingLock.WaitAsync();
try
{
var message = ParseDeliveredMessage(args);
var messageEventArgs = new MessagingEvent(message, args.DeliveryTag.ToString());
onMessageReceived(sender, messageEventArgs);
await onMessageReceived(sender, messageEventArgs);
}
finally
{
_consumingLock.Release();
}
}
return Task.CompletedTask;
};

await Channel.BasicConsumeAsync(QueueName, false, _consumer);
Expand Down Expand Up @@ -89,17 +93,18 @@ public async Task StopConsuming(AsyncEventHandler<ConsumerEventArgs> onConsumerS
{
if (IsConsuming())
{
lock (_consumingLock)
await _consumingLock.WaitAsync();
try
{
if (onConsumerStopped != null)
{
_consumer.UnregisteredAsync += (sender, e) =>
{
onConsumerStopped(sender, e);
return Task.CompletedTask;
};
_consumer.UnregisteredAsync += onConsumerStopped;
}
}
finally
{
_consumingLock.Release();
}

// Must be outside the lock to avoid deadlock
foreach (var tag in _consumer.ConsumerTags)
Expand Down
1 change: 1 addition & 0 deletions src/MerQure.Tools/Buses/Consumer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
await consumer.ConsumeAsync((_, messagingEvent) =>
{
OnMessageReceived(callback, messagingEvent);
return Task.CompletedTask;
});
}

Expand Down Expand Up @@ -52,12 +53,12 @@
callback(this, retryMessage.OriginalMessage);
}

private static string EncodeDeliveryTag(string deliveryTag) //TODO CLEAN !! this is just a fast fix ...

Check warning on line 56 in src/MerQure.Tools/Buses/Consumer.cs

View workflow job for this annotation

GitHub Actions / build

Complete the task associated to this 'TODO' comment.
{
return $"{deliveryTag}_{Guid.NewGuid().ToString()}";
}

private static string DecodeDeliveryTag(string deliveryTag) //TODO CLEAN !! this is just a fast fix

Check warning on line 61 in src/MerQure.Tools/Buses/Consumer.cs

View workflow job for this annotation

GitHub Actions / build

Complete the task associated to this 'TODO' comment.
{
return deliveryTag.Split('_')[0];
}
Expand Down
2 changes: 1 addition & 1 deletion src/MerQure/Clients/IConsumer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/// Start listening on the queue
/// </summary>
/// <param name="onMessageReceived">Handler called each time a message arrives for this consumer.</param>
Task ConsumeAsync(EventHandler<IMessagingEvent> onMessageReceived);
Task ConsumeAsync(AsyncEventHandler<MessagingEvent> onMessageReceived);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

breaking mais j'imagine que c'est pas grave ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est justement le but même. J'avais oublié cet usage lors de la release précédente donc on se retrouve avec du sync over async en Consumer


/// <summary>
/// Indicates if the Consumer is registred on the queue and waiting for messages
Expand All @@ -30,7 +30,7 @@
/// Unregister Consumer from the queue
/// </summary>
/// <param name="onConsumerStopped">Handler called when queu has unregistered the consumer</param>
Task StopConsuming(AsyncEventHandler<ConsumerEventArgs> onConsumerStopped);

Check warning on line 33 in src/MerQure/Clients/IConsumer.cs

View workflow job for this annotation

GitHub Actions / build

Add the 'Async' suffix to the name of this method.

/// <summary>
/// Acknowledge a delivered message.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace MerQure.RbMQ.Events
using MerQure.Messages;

Check warning on line 1 in src/MerQure/Events/MessagingEvent.cs

View workflow job for this annotation

GitHub Actions / build

Remove this unnecessary 'using'.
using RabbitMQ.Client.Events;

namespace MerQure
{
class MessagingEvent : IMessagingEvent
public class MessagingEvent : AsyncEventArgs, IMessagingEvent
{
public IMessage Message { get; set; }

Expand Down
8 changes: 5 additions & 3 deletions tests/MerQure.Tools.Tests/Buses/ConsumerTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using MerQure.Tools.Buses;
using MerQure.Messages;
using MerQure.Tools.Buses;
using MerQure.Tools.Configurations;
using MerQure.Tools.Messages;
using Moq;
using Newtonsoft.Json;
using RabbitMQ.Client.Events;
using System;
using System.Threading.Tasks;
using Xunit;
Expand All @@ -18,9 +20,9 @@ public class ConsumerTests : IDisposable
public ConsumerTests()
{
_mockMerQureConsumer = new Mock<IConsumer>();
_mockMerQureConsumer.Setup(m => m.ConsumeAsync(It.IsAny<EventHandler<IMessagingEvent>>())).Callback((EventHandler<IMessagingEvent> action) =>
_mockMerQureConsumer.Setup(m => m.ConsumeAsync(It.IsAny<AsyncEventHandler<MessagingEvent>>())).Callback((AsyncEventHandler<MessagingEvent> action) =>
{
action(this, new Mock<IMessagingEvent>().Object);
action(this, new MessagingEvent(new Mock<IMessage>().Object, "1"));
});

_mockMessagingService = new Mock<IMessagingService>();
Expand Down
Loading