# Multiple Nurseries For Multiple Steps

**URL:** <https://trio.discourse.group/t/multiple-nurseries-for-multiple-steps/382>\
**Category:** Help and advice\
**Created:** [May 12, 2021, 5:07pm UTC](https://trio.discourse.group/t/multiple-nurseries-for-multiple-steps/382 "2021-05-12T17:07:20Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![b33rcity](https://avatars.discourse-cdn.com/v4/letter/b/b77776/32.png) [@b33rcity](https://trio.discourse.group/u/b33rcity)\
**Post date:** [May 12, 2021, 5:07pm UTC](https://trio.discourse.group/t/multiple-nurseries-for-multiple-steps/382/1 "2021-05-12T17:07:20Z")

</div>

Asynchronous programming is still new territory for me, so naturally I’m having doubts about my approach to this problem with a REST client.

# The problem

To delete an object through the target REST API, other objects associated to the target object must be deleted first. Eg. if

```auto
User1
  | Project1
  | Project2

```

, then I must delete `Project`s 1 and 2 before I can delete `User1`.

# The goal

I want to pass a list of `User`s, delete all of their projects, then delete the users.

# The approach

```python
async def delete_users_and_projects(users: Sequence[str]) -> Tuple[str, ...]:
    # Have to first get each user's projects. Since it could be an arbitrarily long list,
    # I want to do this step as tasks.
    usr_prj = {}
    async with trio.open_nursery() as n:
        for user in users:
            n.start_soon(get_user_projects, user, usr_prj)
            # Assume `get_user_projects` updates `usr_prj[user]` to be the list of projects
    # We have to block until all projects are listed before we can delete them.
    async with trio.open_nursery() as n:
        for prj in itertools.chain.from_iterable(usr_prj.values()):
            n.start_task(delete_project, prj)
    # And again, we have to be sure all projects are gone before we start on the users
    results = []
    async with trio.open_nursery() as n:
        for user in users:
            n.start_task(delete_user, user, results)
            # Assume `delete_user` appends its result to the given list
    return tuple(results)

```

# The concern

I’m fairly sure this will “work”. However, opening three nurseries in sequence like this somehow feels messy at best and at worst like a good way to under-utilize Trio.

Before writing this, I perused the docs one more time and considered using a memory channel to implement a queue for this. I’ve only done something similar with `asyncio` once before, and I did it wrong 😛 Not that I’m opposed to learning to do it right, but before investing the time I wanted to see if I’m even on the right track going that direction, or if I should stick with what I have, or if there’s a third way I’ve not considered.

---

<div class="post-metadata">

**Author:** ![b33rcity](https://avatars.discourse-cdn.com/v4/letter/b/b77776/32.png) [@b33rcity](https://trio.discourse.group/u/b33rcity)\
**Post date:** [May 12, 2021, 9:01pm UTC](https://trio.discourse.group/t/multiple-nurseries-for-multiple-steps/382/2 "2021-05-12T21:01:57Z")

</div>

I found the third way. Perhaps unsurprisingly, it was more abstraction. I wrote a new async function that does all the steps on just one object, then ran _that_ function in tasks for each object I want to delete.

I’m still curious if a queue would be a better solution…
