Estoy usando mensajes diferidos y logro recuperarlos y procesarlos de la manera que quiero. Ahora necesito una forma de eliminarlos (los mensajes normales se pueden "Completar") para que no se queden para siempre, pero no puedo averiguar cómo.
Así es como recupero el mensaje:
var message = await ServiceBusReceiver.ReceiveDeferredMessageAsync( deferredMessage.SequenceNumber, cancellationToken );Y esto es lo que probé primero para borrarlos.
await ServiceBusReceiver.CompleteMessageAsync(message, cancellationToken);Que falló con un error que decía que el bloqueo no era válido, así que lo intenté
await ServiceBusReceiver.RenewMessageLockAsync(message, cancellationToken); await ServiceBusReceiver.CompleteMessageAsync(message, cancellationToken);Pero el error persiste.
EDITAR:
Creé una demostración:
using Azure.Identity; using Azure.Messaging.ServiceBus; const string ToDefer = nameof(ToDefer); const string UnDefer = nameof(UnDefer); const string TopicName = "demo-deferred-sj"; const string ServiceBusNamespace = "#######"; const string SubscriptionName = "all"; var oneSecondMoreThanLockDuration = TimeSpan.FromSeconds(6); var userName = System.Environment.GetEnvironmentVariable("USERNAME"); var serviceBusClient = new ServiceBusClient( $"{ServiceBusNamespace}.servicebus.windows.net", new VisualStudioCredential() ); var sender = serviceBusClient.CreateSender(TopicName); var processor = serviceBusClient.CreateProcessor(TopicName, SubscriptionName, new ServiceBusProcessorOptions { AutoCompleteMessages = false }); var receiver = serviceBusClient.CreateReceiver(TopicName, SubscriptionName); async Task SendMessagesAsync(string kind, string param = "", DateTimeOffset? scheduleTime = null) { var messageId = $"{kind}|{userName}|{param}|{Guid.NewGuid()}"; Console.WriteLine($"Sending {messageId}" + (scheduleTime.HasValue ? $" scheduled for {scheduleTime}" : "") ); var serviceBusMessage = new ServiceBusMessage() { MessageId = messageId }; if (scheduleTime.HasValue) { serviceBusMessage.ScheduledEnqueueTime = scheduleTime.Value; } await sender.SendMessageAsync(serviceBusMessage); } async Task ProcessMessageAsync(ProcessMessageEventArgs args) { Console.WriteLine($"Handling {args.Message.MessageId} "); var messageParts = args.Message.MessageId.Split('|'); var kind = messageParts[0]; var user = messageParts[1]; var param = messageParts[2]; if (user != userName) { Console.WriteLine($"Caution handling message of another user: {user}"); } switch (kind) { case ToDefer: await args.DeferMessageAsync(args.Message); var scheduleTime = args.Message.EnqueuedTime + oneSecondMoreThanLockDuration; await SendMessagesAsync(UnDefer, args.Message.SequenceNumber.ToString(), scheduleTime); break; case UnDefer: var deferredMessage = await receiver.ReceiveDeferredMessageAsync(long.Parse(param)); Console.WriteLine($"Deferd message {deferredMessage.MessageId} processed"); await args.CompleteMessageAsync(args.Message); try { // THIS WOULD DELETE THE MESSAGE IF THE LOCK WAS STILL ON await receiver.CompleteMessageAsync(deferredMessage); } catch (Exception ex) { Console.WriteLine($"Ignoring {ex.Message}"); } break; } } processor.ProcessMessageAsync += ProcessMessageAsync; processor.ProcessErrorAsync += eventArgs => { Console.WriteLine(eventArgs.Exception.Message); return Task.CompletedTask; }; var cancellationTokenSource = new CancellationTokenSource(); await processor.StartProcessingAsync(cancellationTokenSource.Token); await SendMessagesAsync(ToDefer); Console.ReadKey(); cancellationTokenSource.Cancel();De acuerdo con esta discusión de SO , los mensajes diferidos también se pueden devolver mirando mensajes de una cola o suscripción. Puede adquirir los números de secuencia de los mensajes diferidos de esta manera y luego procesarlos o eliminarlos.
Consulte el enlace anterior para obtener más información.