The proprietary codebase I work on is about 50k lines now, heavily using Trio. How many times do you want to code a nursery block in your lifetime? The nursery API is actually fairly low level, and it turns out in most cases we can use simpler abstractions.
Our most popular utility in this area is
wait_any(func1, func2, ...), which just runs the given functions concurrently in a new nursery, and cancels the nursery when any function completes.
wait_any() is easy to understand, not prone to incorrect use, and makes code more readable. A common use is to run one or more processing tasks alongside a monitor which has the option to abort them.
wait_all(func1, func2, ...). It’s not as popular, and users may get confused if one of the functions is
Event.wait() and the event is recycled via clear().
Here are use counts of these vs.
191 wait_any() 137 open_nursery() 58 wait_all()
We also have some async generator utilities.
periodic(duration) is wildly popular among those who can’t be bothered with event-driven programming. Another is the
sync() method pattern, where one task can have its iteration triggered by the end of another task’s iteration (which itself typically uses
385 periodic() 86 obj.sync()
and the winner is…
I think at least
wait_any() should be considered for trio proper. It would spare countless manual nursery blocks.