web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :
Dynamics 365 Community / Blogs / Startspacers / Integration: Claim-check pa...

Integration: Claim-check pattern on Azure function service bus bindings

Basheer17 Profile Picture Basheer17 2,720

Claim-check pattern is also known as reference based messaging. It allows large messages to be processed, which otherwise are not allowed by the messaging platform or slows it down.

It stores the entire message in an external service such as blob storage, gets the reference to the stored payload and replaces the actual message with that reference before sending it to the service.

A sample is added that uses claim-check pattern on service bus message. For usage of the following extension is available in the git repository.

ClaimCheckPattern

using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using Microsoft.Azure.ServiceBus;

namespace ClaimCheckPattern.Common.Extensions
{
    public static class MessageExtensions
    {
        private static readonly string MessageContainer = "servicebus-messages";

        public static async Task<BlobClient> GetBlobClient(BlobServiceClient blobServiceClient, string blobName)
        {
            var blobContainerClient = blobServiceClient.GetBlobContainerClient(MessageContainer);

            await blobContainerClient.CreateIfNotExistsAsync();

            return blobContainerClient.GetBlobClient(blobName);
        }

        public static async Task ClaimCheckOnSend(this Message message, BlobServiceClient blobServiceClient)
        {
            if (message.Size > 250 * 1024)
            {
                var blobClient = await GetBlobClient(blobServiceClient, $"{message.MessageId ?? Guid.NewGuid().ToString()}.json");

                await blobClient.UploadAsync(new MemoryStream(message.Body), overwrite: true);

                message.UserProperties.Add("BlobRef", blobClient.Name);
                message.Body = Encoding.UTF8.GetBytes(blobClient.Name);
            }
        }

        public static async Task ClaimCheckOnReceive(this Message message, BlobServiceClient blobServiceClient)
        {
            if (!message.UserProperties.TryGetValue("BlobRef", out var blobRef))
            {
                return;
            }

            var blobClient = await GetBlobClient(blobServiceClient, (string)blobRef);
            var content = await blobClient.DownloadContentAsync();

            if (content.Value.Content != null) message.Body = content.Value.Content.ToArray();
            await blobClient.DeleteAsync();
        }
    }
}

It is advised to delete the payload from the storage to save cost in the long run, especially if there is a lot of data. Also conditional claim-check pattern should be preferred to avoid overhead and latency issues.

This pattern can also be used if the payload should be accessed only by authorized services. By offloading the payload to an external resource with stricter authentication and authorization, rules can be put in place.


This was originally posted here.

Comments

*This post is locked for comments