Blog Post

Apps on Azure Blog
3 MIN READ

The behavior of Service Bus Topic output binding for Azure Function

Marina_Liu's avatar
Marina_Liu
Icon for Microsoft rankMicrosoft
Jul 19, 2023
Recently, I'm working on a Service Bus topic output binding Azure function and notice that message is sent to the output topic only after the function is executed completely (no matter where you bind the message to the output topic in the code).
 
In order to verify the conclusion, below is a sample Service Bus triggered function with Service Bus Topic output binding (send message to another Service Bus Topic).
{
  "bindings": [
    {
      "name": "mySbMsg",
      "type": "serviceBusTrigger",
      "direction": "in",
      "topicName": "mytopic",
      "subscriptionName": "mysubscription",
      "connection": "marsb1_SERVICEBUS"
    },
    {
        "name": "outputSbQueue",
        "type": "serviceBus",
        "direction": "out",
        "topicName": "myerrortopic",
        "subscriptionName": "myerrorsubscription",
        "connection": "marsb1_SERVICEBUS"
    }
  ]
}
In the function's code, I add some delays and add logs with local time so that we can observe the phenomenon clearly.

module.exports = async function(context, mySbMsg) {

        context.log('JavaScript ServiceBus topic trigger function processed message', mySbMsg);
        context.log('EnqueuedTimeUtc =', context.bindingData.enqueuedTimeUtc);
        context.log('DeliveryCount =', context.bindingData.deliveryCount);
        context.log('MessageId =', context.bindingData.messageId);

        //add logs with GTM+8 timezone
        context.log("Before sending to outbinding topic - ", new Date(new Date().getTime() + (new Date().getTimezoneOffset() + 480) * 60000).toLocaleString());
        context.bindings.outputSbQueue = "send message to my output binding topic";
        await mydelay(60000); //delay 1min after add message to the out binding topic
        context.log("after send to outbinding topic - ",new Date(new Date().getTime() + (new Date().getTimezoneOffset() + 480) * 60000).toLocaleString());

        await mydelay(120000); //delay 2min at the end of the function execution
        context.log("current time at the end of the function execution - ",new Date(new Date().getTime() + (new Date().getTimezoneOffset() + 480) * 60000).toLocaleString());
   
};
function mydelay(time) {
    return new Promise(resolve => setTimeout(resolve, time));
 } 
 
After the function is executed, we can see the timeline as below:
  • 11:52 GTM+8 - executed the code at 10th line (before bind message to the output topic)
  • 11:53 GTM+8 - exceuted the code at 13th line (1min after the message is bind with output topic)
  • 11:55 GTM+8 - executed the code at last (16th) line
Then, we can check the message in the output binding Service Bus topic and find that the message enqueue time is 11:55 GTM+8, which means the message was sent after the code of function is totally executed.
 
 
For now, we should know the mechanism how the Service Bus topic output binding works. And it should be easier to understand why no message is sent to the output topic in below scenario:
module.exports = async function(context, mySbMsg) {

        context.log('JavaScript ServiceBus topic trigger function processed message', mySbMsg);
        context.log('EnqueuedTimeUtc =', context.bindingData.enqueuedTimeUtc);
        context.log('DeliveryCount =', context.bindingData.deliveryCount);
        context.log('MessageId =', context.bindingData.messageId);

        //send message to output binding topic
        context.bindings.outputSbQueue = "send message to my output binding topic";

        //other parts of the code...

        //throw exception at the end of the function
        throw "Message failed";
    
};
Even though the message binding to the output topic (9th line) is ahead of the exception's position (14th line), since the message only sent to the output binding topic after the function execution and the function fails with exception, the message won't be sent to the output binding Service Bus topic.
 
Main Takeways:
  • When function fails with exception, the output binding message won't be sent even though the message is binded ahead of the exception's position;
  • Service Bus Topic output binding message is sent after the function code is totally executed. 
Updated Jul 19, 2023
Version 1.0

2 Comments

  • SeanFeldman's avatar
    SeanFeldman
    Copper Contributor

    Deferred dispatch is great.

    Ideally, it would be nice if this behaviour would be the same with queues as, arguably, messages shouldn't go out if a function call fails.

  • SeanFeldman's avatar
    SeanFeldman
    Copper Contributor

    Deferred dispatch is great.

    Ideally, it would be nice if this behaviour would be the same with queues as, arguably, messages shouldn't go out if a function call fails.