Python Async: ¿Determinista? El desafío revelado

Fuentes: Async Python is Secretly Deterministic | DBOS

El artículo de dbos.dev explora un desafío crucial al desarrollar bibliotecas de ejecución duradera en Python: cómo lograr la determinancia en flujos de trabajo asíncronos. La asincronía, aunque mejora el rendimiento al permitir la ejecución concurrente de tareas (por ejemplo, usando asyncio.gather), complica la reproducibilidad, un requisito fundamental para la recuperación basada en re-ejecución de flujos de trabajo. Si los pasos de un flujo de trabajo se ejecutan en un orden impredecible, la recuperación se vuelve imposible, ya que no se puede garantizar que los pasos se re-ejecuten en el mismo orden que la ejecución original.

La clave para resolver este problema reside en comprender a fondo el funcionamiento interno del bucle de eventos de Python asíncrono. Contrario a la intuición, el bucle de eventos es de un solo hilo y ejecuta las tareas de forma secuencial. Cuando se crea una tarea (por ejemplo, con asyncio.create_task o asyncio.gather), se añade a una cola. El bucle de eventos procesa estas tareas en orden FIFO (First-In, First-Out). Aunque la ejecución dentro de cada tarea puede ser asíncrona y el orden de finalización de las tareas es impredecible, el orden en que se inician las tareas es determinista.

Esta propiedad del orden de inicio determinista se aprovecha en la biblioteca de DBOS. La función decoradora @Step() intercepta la ejecución de cada paso antes de cualquier operación asíncrona (que requiere await). En este punto, asigna un ID de paso único y determinista al paso, basándose en el orden en que se pasaron las corrutinas a asyncio.gather. Esto garantiza que los pasos se procesen en un orden predecible, incluso si la ejecución interna de cada paso es asíncrona. Al conocer el orden de ejecución, la biblioteca puede reproducir el flujo de trabajo de forma fiable durante la recuperación.

En resumen, el artículo destaca que, a pesar de la apariencia de concurrencia, el bucle de eventos de Python asíncrono es fundamentalmente predecible debido a su modelo de ejecución de un solo hilo. Esta predecibilidad permite la creación de flujos de trabajo concurrentes y, al mismo tiempo, deterministas, lo que es esencial para la durabilidad y la recuperación. Este enfoque es particularmente valioso para aplicaciones que requieren flujos de trabajo complejos y fiables, como sistemas de procesamiento de datos, orquestación de microservicios o automatización de procesos empresariales.

DBOS está desarrollando herramientas para simplificar la creación de flujos de trabajo duraderos y deterministas en Python, y anima a los interesados en la fiabilidad de los sistemas a unirse a su comunidad.