This is an example of "parallel" processing using `asyncio`.

We have the following work plan to prepare a dako:

1. Fetch dako rusk
2. Fetch olive oil
3. Fetch tomato
4. Chop tomato
5. Fetch feta
6. Water rusk
7. Oil rusk
8. Put tomato and feta on rusk
9. Store ready dako on countertop

Note that certain steps depend on earlier steps,
e.g. 3→4, 1→6, 6→7, (7, 4, 2)→8, 8→9.

File `kitchen_serial.py` has a straighforward Python implementation.

Execute it as:
  python kitchen_asyncio.py 5
(This creates 5 dakos, one after each other.)

File `kitchen_asyncio_naive.py` has a version which was converted
to use `asyncio` and the jobs will be executed via the `asynio`
task queue, but it will still run serially, because we wait for
each task to be finished before continuing.

Execute it as:
  python kitchen_asyncio_naive.py 5
(This creates 5 dakos, one after each other, using `asyncio`.)

File `kitchen_asyncio_async.py` has a version adds effective
parallelization by starting independent tasks in parallel and only
awaiting when necessary for subsequent steps. Some steps were split
out of the big function `prepare_dako`, to allow them to be awaited
separately.

Execute it as:
  python kitchen_asyncio_async.py 5
(This creates 5 dakos, one after each other, using `asyncio`.)
