Callback-passing style makes async code impossible to follow — a pyramid of doom.
# dirty — pyramid of doom
def build_pipeline(user_data, orders_data, products_data, on_done):
def with_user(user):
def with_orders(orders):
def with_products(products):
on_done({'user': user, 'orders': orders, 'products': products})
fake_products(products_data, with_products)
fake_orders(orders_data, with_orders)
fake_user(user_data, with_user)Refactor `solve(user_data, orders_data, products_data)` using async/await so the function is flat and readable.
Keep solve itself a regular (non-async) function — drive the coroutine internally with asyncio.run(...).
solve({'id': 'u1', 'name': 'Alice'}, [{'id': 'o1'}], [{'id': 'p1'}]) → {'user': ..., 'orders': ..., 'products': ...}
Sample tests