Ir al contenido
  1. Posts/

Python Async Es Secretamente Determinista

··266 palabras·2 mins·

🐍 El gran secreto de asyncio: los tasks empiezan siempre en el mismo orden

Cuando trabajás con workflows durables en Python, necesitás que sean deterministas para poder hacer replay-based recovery. ¿Pero cómo lograrlo si los pasos se ejecutan concurrentemente con asyncio.gather?

🔑 La clave está en el event loop:

  • asyncio es single-threaded: solo ejecuta una tarea a la vez
  • Cuando usás asyncio.gather(coro1, coro2, coro3), las tareas se encolan en orden FIFO
  • Los tasks empiezan siempre en el mismo orden determinista, aunque su finalización sea impredecible
  • Una tarea cede control al event loop solo cuando llama await sobre algo que no está listo
# Este orden de inicio es siempre determinista:
results = await asyncio.gather(step1(), step2(), step3())
# step1 comienza primero, luego step2, luego step3

🏗️ Aprovechándolo para workflows durables: El decorador @Step() de DBOS asigna un ID antes del primer await. Como la asignación ocurre en el orden determinista de inicio, todos los steps tienen IDs consistentes entre ejecuciones → recovery sin problemas.

✅ El modelo single-threaded es en realidad más fácil de razonar que los threads paralelos, porque las tareas solo pueden intercalarse cuando ceden control explícitamente con await.

💡 Explicación en pocas palabras
#

Python async parece caótico porque varias tareas corren “al mismo tiempo”. Pero hay una regla oculta: todas las tareas comienzan en el orden en que las creás. Esto permite que sistemas de recuperación ante fallos puedan reproducir exactamente qué pasó y en qué orden, aunque las tareas terminen en momentos distintos.

Más información en el link 👇

También publicado en LinkedIn.
Juan Pedro Bretti Mandarano
Autor
Juan Pedro Bretti Mandarano