It's been a long time since I didn't write an update post on IoP.
So what's new since IoP command line interface was released?
Two new big features were added to IoP:
- Rebranding: the
grongier.pex
module was renamed toiop
to reflect the new name of the project. - Async support: IoP now supports async functions and coroutines.
Rebranding
The grongier.pex
module was renamed to iop
to reflect the new name of the project.
The grongier.pex
module is still available for backward compatibility, but it will be removed in the future.
Async support
IoP supports async calls for a long time, but it was not possible to use async functions and coroutines directly in IoP.
Before jumping into this new feature, I will explain how async calls work in InterSystems IRIS and present two examples of how to use async calls IoP.
Legacy async calls
Let's see how legacy async calls work:
from iop import BusinessProcess
from msg import MyMessage
class MyBP(BusinessProcess):
def on_message(self, request):
msg_one = MyMessage(message="Message1")
msg_two = MyMessage(message="Message2")
self.send_request_async("Python.MyBO", msg_one,completion_key="1")
self.send_request_async("Python.MyBO", msg_two,completion_key="2")
def on_response(self, request, response, call_request, call_response, completion_key):
if completion_key == "1":
self.response_one = call_response
elif completion_key == "2":
self.response_two = call_response
def on_complete(self, request, response):
self.log_info(f"Received response one: {self.response_one.message}")
self.log_info(f"Received response two: {self.response_two.message}")
Basically they work the same way as async call works in IRIS. The send_request_async
method sends a request to a Business Operation and the on_response
method is called when the response is received.
You can distinguish the responses by the completion_key
parameter.
Send multiple sync requests
It's not exactly a new feature, but it's worth mentioning that you can send multiple sync requests in parallel:
from iop import BusinessProcess
from msg import MyMessage
class MyMultiBP(BusinessProcess):
def on_message(self, request):
msg_one = MyMessage(message="Message1")
msg_two = MyMessage(message="Message2")
tuple_responses = self.send_multi_request_sync([("Python.MyMultiBO", msg_one),
("Python.MyMultiBO", msg_two)])
self.log_info("All requests have been processed")
for target,request,response,status in tuple_responses:
self.log_info(f"Received response: {response.message}")
Here we are sending two requests to the same Business Operation in parallel.
The response is a tuple with the target, request, response and status of each call.
It's really useful when you need to send multiple requests and you don't care about the order of the responses.
Async functions and coroutines
Now let's see how to use async functions and coroutines in IoP:
import asyncio
from iop import BusinessProcess
from msg import MyMessage
class MyAsyncNGBP(BusinessProcess):
def on_message(self, request):
results = asyncio.run(self.await_response(request))
for result in results:
print(f"Received response: {result.message}")
async def await_response(self, request):
msg_one = MyMessage(message="Message1")
msg_two = MyMessage(message="Message2")
# use asyncio.gather to send multiple requests asynchronously
# using the send_request_async_ng method
tasks = [self.send_request_async_ng("Python.MyAsyncNGBO", msg_one),
self.send_request_async_ng("Python.MyAsyncNGBO", msg_two)]
return await asyncio.gather(*tasks)
In this example, we are sending multiple requests to the same Business Operation in parallel using the send_request_async_ng
method.
If you read this post carefully until this point, please comment "Boomerang". This is may be a detail for you, but for me it's mean a lot. Thanks!
The await_response
method is a coroutine that sends multiple requests and waits for all responses to be received.
Thanks to the asyncio.gather
function, we can wait for all responses to be received in parallel.
The benefits of using async functions and coroutines are:
- Better performance: you can send multiple requests in parallel.
- Easier to read and maintain: you can use the
await
keyword to wait for responses. - More flexibility: you can use the
asyncio
module to create complex workflows. - More control: you can use the
asyncio
module to handle exceptions and timeouts.
Conclusion
What are the defirences between send_request_async
, send_multi_request_sync
and send_request_async_ng
?
send_request_async
: sends a request to a Business Operation and waits for the response if theon_response
method is implemented and thecompletion_key
parameter is used.- benefit: you can use async calls the way you are used to.
- drawback: you can be hard to maintain if you need to send multiple requests in parallel.
send_multi_request_sync
: sends multiple requests to the same Business Operation in parallel and waits for all responses to be received.- benefit: it's easy to use.
- drawback: you can control the order of the responses (i mean the list of responses is not ordered).
send_request_async_ng
: sends multiple requests to the same Business Operation in parallel and waits for all responses to be received.- benefit: you can control the order of the responses.
- drawback: you need to use async functions and coroutines.
Happy multithreading!
Author Of article : InterSystems Developer Read full article