0

I am straggling with that issue couple days and need help.

I send message to azure subscription in business layer using that code:

var sender = _serviceBusService.GetSender("event-send");

                    var message = new ServiceBusEvent()
                    {
                        SessionId = sessionId,
                        CourseId = courseId,
                        UserInfo = (BaseRequestUserInfo)userInfo,
                        PlaybackId = playBackId,
                        SsoProvider = userInfo?.SsoProvider,
                        Type = MessageType.SessionEvent
                    };
                    var body = JsonSerializer.Serialize(message);
                    var sbMessage = new ServiceBusMessage(body);
                    sbMessage.ApplicationProperties.Add("SsoProvider", userInfo.SsoProvider);
                    sbMessage.ApplicationProperties.Add("Type", MessageType.SessionEvent.ToString());
                    await sender.SendMessageAsync(sbMessage);

And I created Azure Function which will handle that message. I handle that message and in some cases I need to set that message to subscription one more time with EnqueueTime which depends on Delivery Count. When I debug my function, all properties in ServiceBusMessage object are null. Why does it happen? How could I fix that? Will I see Delicery Count in ApplicationProperties or there are only custom properties?

Azure Function

[FunctionName("VpSessionHandler")]
        public async Task Run([ServiceBusTrigger("event-send", "vp-session-event", Connection = "ServiceBusTopicConnectionString")] ServiceBusMessage mySbMsg,
            [ServiceBus("event-send", Microsoft.Azure.WebJobs.ServiceBus.ServiceBusEntityType.Topic, Connection = "ServiceBusTopicConnectionString")] ICollector<ServiceBusMessage> messageCollector)
        {
            try
            {
                var message = JsonSerializer.Deserialize<ServiceBusEvent>(mySbMsg.Body);
                var accessContext = _eventTrackerService.ChooseAccessTokenContext(message.SsoProvider);
                var accessToken = await accessContext.GetAccessTokenAsync(message.SsoProvider);
                var eventSender = _eventTrackerService.ChooseEventSessionSenderContext(message.SsoProvider);
                var sessionEventModel = new SessionEventModel()
                {
                    PlaybackId = message.PlaybackId,
                    UserInfo = message.UserInfo,
                    AccessToken = accessToken,
                    CourseId = message.CourseId,
                    SessionId = message.SessionId,
                };
                var rez = await eventSender.SendSessionEventApiAsync(sessionEventModel);

                if (!rez.IsSuccessStatusCode)
                {
                    if (mySbMsg.ApplicationProperties.DeliveryCount > 1)
                    {
                        var delayTime = TimeSpan.FromSeconds(Math.Pow(2, mySbMsg.ApplicationProperties.DeliveryCount));
                        mySbMsg.ScheduledEnqueueTime = DateTime.UtcNow.Add(delayTime);

                        messageCollector.Add(mySbMsg);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            _logger.LogInformation($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
        }

P.S. As a first parameter I tried to use ServiceBusReceivedMessage, but I need ServiceBusMessage to add to subscription collection one more time. Additionally, new ServiceBusMessage will have new Delivery Count and it doesn't suit me.

1 Answer 1

1

There's a few things here that are important to consider:

  • The trigger cannot bind to ServiceBusMessage, you must use ServiceBusReceivedMessage. This is why the properties are null when your function is invoked.

  • The delivery count is a broker-owned field; your application should not be attempting to control this value. I'd suggest using an application property on the message to control your application logic.

  • You cannot send a ServiceBusReceivedMessage, you would have to use it to create a ServiceBusMessage regardless of how you were publishing it. This will intentionally remove the delivery count.

  • It is possible to set the delivery count for a ServiceBusMessage or ServiceBusReceivedMessage - if you do so directly on the underlying AmqpAnnotatedMessage.

  • Even if you set the delivery count via the AMQP message, the service may ignore or change it, as it sees fit - this is considered a broker-owned field. I don't know what the current behavior is, but you cannot depend on it not to change over time.

Sign up to request clarification or add additional context in comments.

5 Comments

It is better to create a custom property instead of using delivery count, am I right? Depend on value of that custom property (for example 1,2,3 etc.) I would like to increase enqueue time.
Correct; using an application property would be a better approach.
What could I do if changing for Delivery Count sometimes ignore by service bus? Should Service Bus stop handle message when it reach max delivery count which I set programmatically? Should I set ApplicationProperties in AmqpAnnotatedMessage too? I noticed that if I set ApplicationProperties just in ServiceBusMessage and than define AmqpAnnotatedMessage for that message, my custom property doesn't change, but if I set custom property in AmqpAnnotatedMessage it change correctly .
You cannot manipulate "DeliveryCount" via application properties - you'd be creating your own version of this field to drive your logic from. Service Bus behavior for a delivery count that you force via AMQP message is not guaranteed. You can do nothing to influence or control it. Again, "DeliveryCount" is a broker-owned field - your code should not be trying to control this.
Right now I see that. Thanks very much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.