From reading Nathaniel’s blog posts, I understand that avoiding callbacks is a central concept of structured concurrency. The Trio design docs back this up:
Task spawning is always explicit. No callbacks, no implicit concurrency, no futures/deferreds/promises/other APIs that involve callbacks.
However, there are APIs in trio which use what I would call callbacks - functions passed in which will be called when something happens. Specifically, serve_tcp() takes a
handler function to be called for a new incoming connection.
I understand that this doesn’t break structured concurrency: the new tasks are either children of the task running
serve_tcp, or belong to a nursery explicitly passed in. And the docs have a warning that uncaught errors in handlers will crash the server. But is there a good explanation for why callbacks are a sensible choice in this specific case? Or do other people not consider the
handler argument a callback?
For context: I’m playing with some code using Trio, and a contributor likes a design where each incoming message triggers a callback in a newly started task. I’ve got a feeling that this is best avoided, even if it’s technically possible with Trio. But I can’t articulate why exactly it’s different from serve_tcp’s callbacks on new connections.