-
Notifications
You must be signed in to change notification settings - Fork 617
Description
Describe the bug
It's unclear whether this is a bug or intended behavior, but the ShutdownEventArgs.CancellationToken on the AsyncEventingBasicConsumer.ShutdownAsync event is always in a canceled state (IsCancellationRequested = true) when, for example, the RabbitMQ server is shut down or the channel is closed using IChannelExtensions.CloseAsync.
This seems inconsistent with the documentation for the event's CancellationToken, which states:
It's important for your handler to pass this token along to any asynchronous or long-running synchronous operations...
The immediate cancellation makes it unclear how the token is meant to be used in practice.
Reproduction steps
Minimal Example:
[Test]
public async Task Test(CancellationToken ct = default)
{
var connectionFactory = new ConnectionFactory
{
Endpoint = new AmqpTcpEndpoint(ContainerContext.GetRabbitMqUri()),
UserName = ContainerContext.UserName,
Password = ContainerContext.UserPassword,
};
await using var connection = await connectionFactory.CreateConnectionAsync(ct);
await using var channel = await connection.CreateChannelAsync(cancellationToken: ct);
var declareOk = await channel.QueueDeclareAsync(queueName, true, false, false, cancellationToken: ct);
await channel.QueueBindAsync(queueName, exchangeName, "", cancellationToken: ct);
await using var consumerChannel = await connection.CreateChannelAsync(cancellationToken: ct);
var consumer = new AsyncEventingBasicConsumer(consumerChannel);
consumer.ShutdownAsync += async (_, args) =>
{
// args.CancellationToken is always initially canceled?
await CleanupAsync(args.CancellationToken);
};
var consumerTag = await consumerChannel.BasicConsumeAsync(queueName, true, consumer, cancellationToken: ct);
await consumerChannel.CloseAsync(cancellationToken: ct); // close consumer channel or shutdown rabbitmq server
await Task.Delay(TimeSpan.FromSeconds(10), ct);
}
private async Task CleanupAsync(CancellationToken ct)
{
// do some cleanup ...
await Task.Delay(TimeSpan.FromSeconds(1), ct);
}Expected behavior
The CancellationToken should remain non-canceled when the ShutdownAsync handler is invoked, allowing the handler to propagate the token to any asynchronous or long-running operations as intended. Cancellation should only be requested if the shutdown process itself is being canceled externally.
Additional context
Version 7.2.0