1
votes

Background & current design

I have some services (ASP.Net Core) that send messages to an Azure Service Bus queue. An Azure Function processes the message, using a ServiceBusTrigger that targets the queue i.e. only a single queue & ServiceBusTrigger. The Message UserProperties property (IDictionary) is populated with a “type” entry, which identifies the message body and how to deserialize it (into a known type), and process it. The current design seems a bit crude. Extending it essentially means extending a case statement to include new message types and processes. Or add more queues, each dedicated to a specific message type, and each with a dedicated processor. i.e. a single Azure Function with multiple ServiceBusTriggers targeting each queues\message type.

The question: Is there a better way to do this? And what other designs\architectures have been used successfully?

2
This question is probably going to get some primarily opinion based answers. Please refer to How to Ask. On-topic: By design, a queue is meant for a specific message type. Different types of processing mean different processes. Creating a new queue can be completely automated. - rickvdbosch
Opinionated answers are fine (with me). I know they are discouraged by the stack overlords... but I am hoping to get some ideas before the inevitable "Question marked as...". I have read the How to Ask, thanks for that gem. - user657527
@Arunprabhu thank you for your answer, Imrans' answer has more details so I will mark it as correct but both helped. Thank you both. Topics\subscriptions definitely seems like the way to go, not sure how I missed that. - user657527

2 Answers

1
votes

Topic-Subscription

I would like to extend the answer by @arnumprabhu. If you want to use different message types then you should be looking for Topic-Subscription model. This way your publish the message at topic and services that are subscribed to it can get the message. Each topic can have many subscriptions and each subscription can listen to only particular type of messages or all them. e.g. You publish 3 messages. BookingConfirmed, PaymentProcessed, OrderDelivered. You have 3 subscriptions which can listen to any of the above messages or all of them . Say your subscription (Say name of subscription is Tracking) decides to listen to 2 messages BookingConfirmed , PaymentProcessed. When ever the message is published to topic , your subscription gets copy of these messages

Azure function

Your azure function can subscribe to the subscription (Tracking) and only listen to the messages arrived on this subscription. On a very high level it could look something like this.

[FunctionName("myfunction")]
    public static async void Run([ServiceBusTrigger("topicName", "Subscriptionname", Connection = "ServiceBus")]Message serviceBusMessage, ILogger log)
    {            
        EventStore eS = new EventStore();
        await eS.UpdateData(serviceBusMessage);

        // log.LogInformation($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
    }
public class EventStore
{
    public async Task UpdateData(Message msg)
    {        

        try
        {
            if (msg.Label == "BookingAdd")
            {
                BookingAddIntegrationEvent eventMsg = JsonConvert.DeserializeObject<BookingAddIntegrationEvent>(Encoding.UTF8.GetString(msg.Body));

                string messageType = "BookingCreated";

                BookingCreated bookingCreated = new
                   BookingCreated(eventMsg.BookingId, string.Empty, eventMsg.Id
                   , messageType, eventMsg.CreationDate, eventMsg.Origin, eventMsg.Destination);

                bookingId = eventMsg.BookingId;
                tracking.BookingAdd(bookingCreated);

            }
            else if (msg.Label == "OrderPicked")
            {
                OrderPickedIntegrationEvent eventMsg = JsonConvert.DeserializeObject<OrderPickedIntegrationEvent>(Encoding.UTF8.GetString(msg.Body));

                string messageType = "OrderPicked";

                OrderPicked orderPicked = new
                    OrderPicked(eventMsg.BookingId, eventMsg.Description, eventMsg.Id
                    , messageType, eventMsg.CreationDate);

                bookingId = eventMsg.BookingId;
                tracking.OrderPicked(orderPicked);

            }


        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

}

1
votes

If you want the messages to be processed from different clients(functions) you can go with Service Bus Topic Subscriptions. Topics are recommended for multiple subscribers.

You can create Rules for each Subscription and based on the user properties and rules configured, the messages will automatically fall in to the respective Subscription, from which the Functions can be triggered. Check here for more details about Topic Subscriptions.