Artículo
· 8 ago, 2024 Lectura de 5 min

Interoperabilidad En Python: actualización soporte async

Hacía mucho tiempo que no escribía un post de actualización en IoP (Interoperabilidad en Python).

image

¿Qué hay de nuevo desde el lanzamiento de la interfaz de línea de comandos de IoP?

Dos nuevas grandes características se han añadido a IoP:
- Rebranding: el módulo grongier.pex fue renombrado a iop para reflejar el nuevo nombre del proyecto.
- Soporte asíncrono**: IoP ahora soporta funciones asíncronas y corrutinas.

Rebranding

El módulo grongier.pex ha sido renombrado a iop para reflejar el nuevo nombre del proyecto.

El módulo grongier.pex sigue disponible para compatibilidad con versiones anteriores, pero se eliminará en el futuro.

Soporte Async

IoP soporta llamadas asíncronas desde hace mucho tiempo, pero no era posible utilizar funciones asíncronas y corrutinas directamente en IoP.

Antes de saltar a esta nueva característica, voy a explicar cómo funcionan las llamadas async en InterSystems IRIS y presentar dos ejemplos de cómo utilizar las llamadas async IoP.

Llamadas asíncronas heredadas

Veamos cómo funcionan las llamadas async legacy:

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}")

Básicamente funcionan de la misma manera que las llamadas asíncronas en IRIS. El método send_request_async envía una petición a una Operación de Negocio y el método on_response es llamado cuando se recibe la respuesta.

Podéis distinguir las respuestas por el parámetro completion_key.

Enviar múltiples peticiones de sincronización

No es exactamente una nueva característica, pero vale la pena mencionar que se pueden enviar múltiples solicitudes de sincronización en paralelo:

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}")

Aquí estamos enviando dos peticiones a la misma Operación de Negocio en paralelo.

La respuesta es una tupla con el objetivo, la petición, la respuesta y el estado de cada llamada.

Es realmente útil cuando necesitáis enviar múltiples peticiones y no te importa el orden de las respuestas.

Funciones asíncronas y corrutinas

Ahora vamos a ver cómo utilizar funciones asíncronas y corrutinas en 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)

En este ejemplo, estamos enviando múltiples peticiones a la misma Operación de Negocio en paralelo usando el método send_request_async_ng.

Si habéis leído atentamente este post hasta este punto, comentad «Boomerang». Esto puede ser un simple detalle para vosotros, pero para mi significa mucho. Gracias.

El método await_response es una corrutina que envía múltiples peticiones y espera a recibir todas las respuestas.
Gracias a la función asyncio.gather, podemos esperar a que se reciban todas las respuestas en paralelo.

Las ventajas de utilizar funciones asíncronas y corrutinas son:

  • Mejor rendimiento: podéis enviar múltiples peticiones en paralelo.
  • Más fácil de leer y mantener: podéis usar la palabra clave await para esperar las respuestas.
  • Más flexibilidad: podéis utilizar el módulo asyncio para crear flujos de trabajo complejos.
  • Más control: podéis utilizar el módulo asyncio para manejar excepciones y tiempos de espera.

Conclusión

¿Cuáles son las diferencias entre send_request_async, send_multi_request_sync y send_request_async_ng?

  • send_request_async: envía una petición a una Operación de Negocio y espera la respuesta **si** se implementa el métodoon_responsey se utiliza el parámetrocompletion_key`.
    • ventaja: podéis utilizar las llamadas async de la forma habitual.
    • desventaja: puede ser difícil de mantener si necesitáis enviar múltiples peticiones en paralelo.
  • send_multi_request_sync`: envía múltiples peticiones a la misma Operación de Negocio en paralelo y espera a que se reciban todas las respuestas.
    • ventaja: es fácil de usar.
    • desventaja: se puede controlar el orden de las respuestas (es decir, la lista de respuestas no está ordenada).
  • send_request_async_ng`: envía múltiples peticiones a la misma Operación de Negocio en paralelo y espera a que se reciban todas las respuestas.
    • ventaja: se puede controlar el orden de las respuestas.
    • desventaja: es necesario utilizar funciones asíncronas y coroutines.

¡Feliz multithreading!

Comentarios (0)1
Inicie sesión o regístrese para continuar