IRIS Embedded Python with Azure Service Bus (ASB) use case
Tags: azure, beginners, programming
Published: 2022-10-28 19:49:49

## **Overview**

We started to use Azure Service Bus (ASB) as an enterprise messaging solution 3 years ago. It is being used to publish and consume data between many applications in the organization. Since the data flow is complex, and one application’s data is usually needed in multi applications the “publisher” \---> ”multiple subscribers” model was a great fit. The ASB usage in the organization is dozens of millions of messages per day, while IRIS platform is having around 2-3 million messages/day.

## **The Problem with ASB**

When we started with the ASB integration, we found that the AMQP protocol is not an "out of the box" for IRIS deployment, so we were looking for an alternative solution to be able to communicate with the ASB.

## **The solution**

We developed a local windows service (in .NET and Swagger) that was doing the actual communication to the ASB. It was installed at the same machine with IRIS. We sent the messages to ASB to this local windows service (using: localhost and doing a REST API) and that service did the rest. This solution was working fine for few years, but monitoring the traffic, debugging the "lost" messages and measuring the overall performance was very difficult. The fact that we had this local windows service as “a man in the middle” is always not the best architecture.

## **IRIS Embedded Python Early Access Program (EAP)**

I have been asked (or volunteered I can’ remember) to participate in the Early Release Program (ERP) for the Embedded Python. This was very exciting for me, to be able to test new features, give feedback to the development team. It also felt very good to be active in participating and influencing with this product development. At this stage we started to test the Embedded Python for the ERP and decided to check if we can lavarge Embedded Python to do solve “real” problems. Taking the “IRIS to ASB direct connectivity” for this purpose was very natural.

## **The POC (proof of concept****)**

We started to code the solution and found that using the Microsoft ASB library for Python will make our life (and coding) much easier. The initial stage was to develop a function that can connect to a specific topic in ASB and received messages. This was done quite fast (1 day of development) and then we progressed to the “publish” (sending to ASB) phase.

Additional few days took us to develop the whole “envelope” for those send & receive functions: we have built the following:

  * A proper incoming and outgoing “staging area” to control the flow of in/out messages
  * A central mechanism to store the ASB in & out traffic to be able to have proper statistics and performance measurements
  * A CSP monitoring page to enable/disable services, show statistics and give alerts on any issues

## The implementation

### Preliminary Configuration

Prior to the use of Microsoft ASB libraries for Python, there is a need to install them into a ..\python dedicated folder.  
we choosed to use ../mge/python/ but you may use any other folder you like (initially it was an empty folder)  
Those need to executed from an elevated CMD (on windows) or by using an elevated user (on Linux):

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  ..\bin\irispip install --target ..\mgr\python asyncio 
  
  <p>
    ..\bin\irispip install --target ..\mgr\python azure.servicebus
  </p>
</div>

### Receiving messages to ASB (consuming)

We have a ClassMethod with some parameters:

  * The topiId - The ASB is divided to topics from which you consume messages
  * subscriptionName <span> </span>- Azure subscription name
  * <span> </span>connectionString <span> </span>- To be able to connect to the topic you are subscribed to

Note that we are using `[ Language = python ]` to indicate that this ClassMethod is written in Python (!)

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  ClassMethod retrieveASB(topicId As %Integer = 1, topicName As %String = "", subscriptionName As %String = "", connectionString As %String = "", debug As %Integer = 1, deadLetter As %Integer = 0) As %Integer [ Language = python ]
</div>

To use the ASB library, we first need to import `ServiceBusClient` and `ServiceBusSubQueue` libraries:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
   from azure.servicebus import ServiceBusClient,ServiceBusSubQueue
</div>

to be able to interact with IRIS (e.g. to run code) we also need to:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  import iris  
</div>

At this stage we can use the ASB libraries:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  with ServiceBusClient.from_connection_string(connectionString) as client: 
  
  <p>
        with client.get_subscription_receiver(topicName, subscriptionName, max_wait_time=1, sub_queue=subQueue) as receiver:
  </p>
  
  <p>
            for msg in receiver:
  </p>
</div>

At this point we have a Python object "msg" (stream) where we can pass it (as a stream of course) to IRIS and store it directly in the database:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  result = iris.cls("anyIRIS.Class").StoreFrom Python(stream)
</div>

### Sending messages to ASB (publishing)

We have a ClassMethod with some parameters:

  * topicName <span> </span>- The Topic we want to publish to (here we need to pass the name not the id)
  * connectionString <span> </span>- To be able to connect to the topic you are subscribed to
  * JSONmessage <span> </span>- the message we want to send (publish)

Note that we are using `[ Language = python ]` to indicate that this ClassMethod is written in Python (!)

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  ClassMethod publishASB(topicName As %String = "", connectionString As %String = "", JSONmessage As %String = "") As %Status [ Language = python ]
</div>

To use the ASB library, we first need to import `ServiceBusClient` and `ServiceBusMessage` libraries:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  from azure.servicebus import ServiceBusClient, ServiceBusMessage
</div>

Using the ASB Libraries is then very easy:

<div style="background:#eeeeee;border:1px solid #cccccc;padding:5px 10px;">
  try: 
  
  <p>
            result=1
  </p>
  
  <p>
            with ServiceBusClient.from_connection_string(connectionString) as client:
  </p>
  
  <p>
                with client.get_queue_sender(topicName) as sender:
  </p>
  
  <p>
                    single_message = ServiceBusMessage(JSONmessage)
  </p>
  
  <p>
                    sender.send_messages(single_message)        
  </p>
  
  <p>
        except Exception as e:
  </p>
  
  <p>
            print(e)
  </p>
  
  <p>
            result=0
  </p>
  
  <p>
        return result
  </p>
</div>

## Benefits of using direct ASB connectivity

  * Much faster than using the "old alternative" of the "windows local service"
  * Easy to monitor, collect statistics, debug issues
  * Decommissioning the "man in the middle" (windows local service) reduces a potential "point of failure"
  * Ability to manage the "dead letters" for any topic automatically and to make the ASB re-send those messages to the subscriber's topic

## Credits

I would like to thank @David.Satorres5186<span> (our senior developer for IRIS) for his </span>huge contribution in design, coding & testing.<span> Without his help this project wouldn't be possible.</span>