Spawning tokio tasks within tokio tasks

I feel like I should preface my question by saying that Rust is essentially my first programming language and so maybe I'm asking about things that aren't specific to Rust, although my questions do relate to popular Rust teaching materials.

I like to use the actors with tokio pattern in my Rust applications, where you spawn a task holding an mpsc::Receiver, while another part of the application holds a sender that sends messages along with the sender of a tokio oneshot channel to return a response from the receiving actor.

My question is about more complex applications using that pattern: is it a "good" thing, i.e. is it a fairly common and reliable way of designing applications, to spawn tasks within a task?

For example, say my receiver actor in the pattern described above is receiving jobs that I want to handle asynchronously, possibly even dispatching the jobs via gRPC to other applications that do some sort of work that needs to be waited on. Is there something "wrong" or inadvisable about spawning tasks within my receiver task to handle the dispatching of those jobs, apart from the resource overhead of potentially spawning lots of tasks?

On the matter of the overhead of spawning lots of tasks, aside from the chapter in The Rust Programming Language where we learn how to implement a threadpool, where should I look for guidance on how to do that in a production application?

Sure! The only I'd ask yourself is why you chose the actor pattern in particular. Will a particular resource (mutable objects, etc) be owned by an actor?

Nope!

Since you're using tokio (I assume from what you said), you would spawn tasks with tokio's spawn method, not using a threadpool. You can mix async and threads, but I wouldn't start with that since it is more complex and only needed in certain cases.

2 Likes

FWIW, while nothing stops a task calling tokio::spawn to produce another task, it's worth keeping in mind that beyond that, there is no sense of a task being "within" another, unlike something like scoped threads. The original task will not pause for the task it spawned to complete unless you specifically have it await on the JoinHandle that spawn gives you back. If you don't await the handle, the spawning task will continue onwards heedlessly, and the spawned task's return value will disappear into the void when it does eventually complete.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.