2019-10-10 14:03:12 +00:00
|
|
|
using System;
|
2019-08-13 18:30:04 +00:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
using RabbitMQ.Client;
|
|
|
|
using Tapeti.Default;
|
|
|
|
|
|
|
|
namespace Tapeti.Connection
|
|
|
|
{
|
2021-10-07 13:38:43 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Called to report the result of a consumed message back to RabbitMQ.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="expectedConnectionReference">The connection reference on which the consumed message was received</param>
|
|
|
|
/// <param name="deliveryTag">The delivery tag of the consumed message</param>
|
|
|
|
/// <param name="result">The result which should be sent back</param>
|
2021-09-21 14:17:09 +00:00
|
|
|
public delegate Task ResponseFunc(long expectedConnectionReference, ulong deliveryTag, ConsumeResult result);
|
|
|
|
|
|
|
|
|
2019-08-13 18:30:04 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Implements the bridge between the RabbitMQ Client consumer and a Tapeti Consumer
|
|
|
|
/// </summary>
|
2023-04-06 05:25:01 +00:00
|
|
|
internal class TapetiBasicConsumer : DefaultBasicConsumer
|
2019-08-13 18:30:04 +00:00
|
|
|
{
|
|
|
|
private readonly IConsumer consumer;
|
2021-09-21 14:17:09 +00:00
|
|
|
private readonly long connectionReference;
|
|
|
|
private readonly ResponseFunc onRespond;
|
2019-08-13 18:30:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-09-21 14:17:09 +00:00
|
|
|
public TapetiBasicConsumer(IConsumer consumer, long connectionReference, ResponseFunc onRespond)
|
2019-08-13 18:30:04 +00:00
|
|
|
{
|
|
|
|
this.consumer = consumer;
|
2021-09-21 14:17:09 +00:00
|
|
|
this.connectionReference = connectionReference;
|
2019-08-13 18:30:04 +00:00
|
|
|
this.onRespond = onRespond;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2023-04-06 05:25:01 +00:00
|
|
|
public override void HandleBasicDeliver(string consumerTag,
|
2021-05-29 19:51:58 +00:00
|
|
|
ulong deliveryTag,
|
|
|
|
bool redelivered,
|
|
|
|
string exchange,
|
|
|
|
string routingKey,
|
|
|
|
IBasicProperties properties,
|
|
|
|
ReadOnlyMemory<byte> body)
|
2019-08-13 18:30:04 +00:00
|
|
|
{
|
2021-07-05 08:28:49 +00:00
|
|
|
// RabbitMQ.Client 6+ re-uses the body memory. Unfortunately Newtonsoft.Json does not support deserializing
|
|
|
|
// from Span/ReadOnlyMemory yet so we still need to use ToArray and allocate heap memory for it. When support
|
|
|
|
// is implemented we need to rethink the way the body is passed around and maybe deserialize it sooner
|
|
|
|
// (which changes exception handling, which is now done in TapetiConsumer exclusively).
|
|
|
|
//
|
|
|
|
// See also: https://github.com/JamesNK/Newtonsoft.Json/issues/1761
|
|
|
|
var bodyArray = body.ToArray();
|
2023-04-06 05:25:01 +00:00
|
|
|
|
|
|
|
// Changing to AsyncDefaultBasicConsumer does not mean HandleBasicDeliver runs in parallel, the Task.Run would
|
|
|
|
// still be necessary, which is why TapetiBasicConsumer is a DefaultBasicConsumer.
|
|
|
|
Task.Run(async () =>
|
2023-03-31 05:42:59 +00:00
|
|
|
{
|
2023-04-06 05:25:01 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
var response = await consumer.Consume(exchange, routingKey, new RabbitMQMessageProperties(properties), bodyArray);
|
|
|
|
await onRespond(connectionReference, deliveryTag, response);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
await onRespond(connectionReference, deliveryTag, ConsumeResult.Error);
|
|
|
|
}
|
|
|
|
});
|
2019-08-13 18:30:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|