private async Task ResubmitMessageAsync(Message message, Microsoft.Azure.ServiceBus.Core.MessageSender sender, int resubmitCount)
        {
            // https://markheath.net/post/defer-processing-azure-service-bus-message
            var clone = message.Clone();

            clone.UserProperties["ResubmitCount"] = resubmitCount + 1;
            clone.ScheduledEnqueueTimeUtc         = DateTime.UtcNow
                                                    .AddMinutes(RetryTemporaryErrorsAfterMinutes)
                                                    .AddSeconds(jitterer.Next(0, 120)); // plus some jitter up to 2 minutes
            await sender.SendAsync(clone);
        }
        public async Task Defer(TimeSpan tryAgainIn)
        {
            // Deferral of a message is implemented per the recommendation given here:
            // https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-deferral#message-deferral-apis
            // We defer the message in Azure Service Bus, effectively hiding it indefinitely.
            // We then send a new "control" message to the same queue that contains the sequence number of the deferred message.
            // The control message is scheduled for delivery at a certain time.
            // The message pump will handle the control message by getting the sequence number and using it to obtain the deferred message.
            var sender = new Microsoft.Azure.ServiceBus.Core.MessageSender(_messageReceiver.ServiceBusConnection,
                                                                           _messageReceiver.Path, _messageReceiver.RetryPolicy);

            var controlMessage = new Message();

            controlMessage.UserProperties.Add(Constants.HeaderKeys.RPDeferredMessageSequenceNumber, _message.SystemProperties.SequenceNumber);
            controlMessage.UserProperties.Add(Constants.HeaderKeys.RPContextId, _settings.ContextId);
            //Copy the tenant Id
            if (_message.UserProperties.TryGetValue(Constants.HeaderKeys.RPTenantId, out var messageTenantId))
            {
                controlMessage.UserProperties.Add(Constants.HeaderKeys.RPTenantId, messageTenantId);
            }

            controlMessage.ScheduledEnqueueTimeUtc = DateTime.UtcNow.Add(tryAgainIn);
            controlMessage.PartitionKey            = _message.PartitionKey; // Ensure the control message goes to the same partition as the underlying message so transactions work

            // We want to use a transaction if we're not already in a transaction scope
            var useTransaction = !_isTransactional;

            using (var tx = useTransaction ? new TransactionScope(TransactionScopeAsyncFlowOption.Enabled) : null)
            {
                await sender.SendAsync(controlMessage).ConfigureAwait(false);

                if (_deferralControlMessage == null)
                {
                    await _messageReceiver.DeferAsync(_message.SystemProperties.LockToken)
                    .ConfigureAwait(false);
                }
                else
                {
                    await _messageReceiver.AbandonAsync(_message.SystemProperties.LockToken)
                    .ConfigureAwait(false);
                }

                // If we are deferring a message that was already deferred, we are sending a new control message, so complete
                // the current control message.
                if (_deferralControlMessage != null)
                {
                    await _messageReceiver.CompleteAsync(_deferralControlMessage.SystemProperties.LockToken).ConfigureAwait(false);
                }

                tx?.Complete();
            }
        }
Exemplo n.º 3
0
        static async Task Sender()
        {
            var queue  = "myfirstqueue";
            var sender = new Microsoft.Azure.ServiceBus.Core.MessageSender(NamespaceConnectionString, queue);
            var text   = Console.ReadLine();

            while (text != "q")
            {
                var message           = new Microsoft.Azure.ServiceBus.Message(System.Text.Encoding.UTF8.GetBytes(text));
                var messageWithOffset = new Microsoft.Azure.ServiceBus.Message(System.Text.Encoding.UTF8.GetBytes(text + " with offset"));

                await sender.ScheduleMessageAsync(messageWithOffset, DateTimeOffset.Now.AddSeconds(3));

                await sender.SendAsync(message);

                text = Console.ReadLine();
            }

            await sender.CloseAsync();
        }