I was trying to figure out how to ensure sequenced processing of the messages (the messages are processed in the same order they are received) with Azure Logic Apps. Here my requirement is to make sure the subsequent message should not be processed until the previous one’s processing is complete and it should work the same way for the lifetime of the process. Example: Multiple senders can send (related or unrelated) messages (new, updates within milliseconds or minutes or days apart) to my topic subscription. The first messages that comes in, should always go out processed before the second message gets picked up for processing.
I utilized the following properties of Azure Service Bus and Logic Apps to achieve my desired requirement.
Service Bus Sessions: To realize FIFO guarantee in messaging, Microsoft recommends to use Service Bus Sessions. Sessions enable joint and ordered handling of unbounded sequences of messages which is what I exactly need. Any sender can create or share a session while submitting messages into a topic or queue by setting the SessionId property to some application-defined identifier that is unique to the session. So I can create a session and keep it on forever by publishing the messages to the topic subscription with the same SessionId.
Service Bus Message Sequencing: Senders can submit messages to the topic within milliseconds timeframe. I would need a better Sequencing technique to absolutely order the messages. Service Bus came to the rescue again. Message Sequencing and timestamping are two features that are always enabled on all Service Bus entities and surface through the SequenceNumber and EnqueuedTimeUtc properties of received or browsed messages. The sequence number can be trusted as a unique identifier since it is assigned by a central and neutral authority and not by clients. It also represents the true order of arrival, and is more precise than a time stamp as an order criterion, because time stamps may not have a high enough resolution at extreme message rates and may be subject to (however minimal) clock skew in situations where the broker ownership transitions between nodes. I don’t have to do anything for this as the sequencing is auto-enabled.
Service Bus Peek-Lock Mode: This mode puts an exclusive lock on the message/session and retains the lock for the set duration until the receiving client (Logic App) completes (dequeues) the message. This is very critical in my case as I don’t want any subsequent messages to be made available until the current message is explicitly marked complete.
Logic Apps Next Available property on the Service Bus trigger: Enabling this property makes sure every time the logic app triggers, it will get only the next available message on the session.
I think we are all set to address the requirement by leveraging Azure Logic Apps and Azure Service Bus.
Azure Service Bus Standard Tier can process message up to 256 KB in size. If your message size exceeds the limit, you can keep the message content elsewhere (on a blob storage or a file share or a FTP site and publish only the message metadata to the Service Bus Topic and have your Logic App directly read and process the content from where you have stored your file) or you can consider to go Premium that can process 1 MB.
Here is what I did:
- Created a Service Bus namespace and a Topic on the Azure Portal
- Leveraged Service Bus Explorer to create subscriptions and filters (Enabled Sessions on just one so we can differentiate how the Session-aware and Session-unaware messages are processed) (Azure Portal doesn’t have the feature to create Filters on Subscriptions yet)
- Create three Logic Apps (First to publish PO transactional messages (ordered processing required) and Supplier master messages (ordered processing not required), second to sequentially process the PO messages and the third to process the Supplier data )
Let’s take a detailed look.
Service Bus Namespace creation:
- Log on to Azure Portal –> Create a resource –> Search for “Service Bus” and create the namespace.
2. Open Service Bus namespace on the Service Bus Explorer by copying over the connection string from the Azure Portal. Create Subscriptions and the appropriate Filters to receive only the intended messages. And set the Lock duration to 1 minute.
Important: Enable Session on the Purchase Order subscription
The client holds an exclusive lock on all messages with that session’s SessionId that exist in the subscription, and also on all messages with that SessionId that still arrive while the session is held. The lock duration for each message on the session should be carefully set. If the client takes more time to process a message than the set duration, the client would lose the lock on the message and the message would be released for the next available subscriber or in our case, the next logic app instance. If required, lock on the session can be renewed by the client while the message is being processed. In case a message failed processing inside the application, the message should be dead-lettered so the next message will be made available.
3. Now the Service Bus Topic is ready. The subscription ‘subscription-purchaseorders’ will receive the purchase order messages that would be sent with the message property {Interface = ‘PurchaseOrder’} and SessionId = PO and the subscription ‘subscription-suppliers’ will receive the supplier messages that would be sent with the message property {Interface = ‘Supplier’} and no SessionId
Let’s see how to design the Logic Apps:
Logic App 1: Publish Purchase Order and Supplier messages to the Topic
Logic App 2: Consume Purchase Order Messages from the Topic (Ordered processing)
Logic App 3: Consume Supplier Messages from the Topic
Though the logic app was running every 5 seconds, the messages were picked up only after the previous message was complete i.e., every instance took almost a minute to process and mark the message complete so the next message was made available. Also take a look at the skipped triggers which means while a message was being processed, even when the logic app attempted to receive messages from the subscription, no message was available though they were on the subscription and trigger was skipped. Hooray!
This was very helpful!
As a bit of feedback on the blog layout, I found the rotating images difficult to interact with. I, personally, find it more helpful to have images shown individually and clickable (to reveal a larger version).
LikeLike
Thank you for your comment and feedback!
LikeLike
We implemeted the same but facing issue with the Queue message timeout. The next message has to wait for the first message to timeout. This is happening even after we are completing the message at end. The Timeout we kept is 4 minute and next message has to wait for 4 minute
LikeLike