Axum and lifetimes ("scoped routes")

Td;dr: why does axum require Arc for state?
Similar to threads vs "scoped threads", why can't we use local reference for the state?

Background:
I write a lot of simple endpoints, typically need some state.
So, my routes get an argument which is an Arc.
But, this should be a local refence really, since my service should stop before the state is deallocated.

So, question:
Is there a way to spawn a "scoped endpoint" in axum, which blocks until it is stopped?

Is this just because the axum code simplifies a lot without having reference all over the place? (Which would be a reasonable argument; I skimmed the code and saw already some lifetimes)

I also want to add that I'm happy with axum as it is, this issue appears mostly when on boarding new devs. This question is just me being curious.

It is very common to use Arc in any kind of asynchronous program. The 'static requirement for a axum router's state boils down to the fact that non-'static types can't be guaranteed to outlive a task spawned by tokio, the asynchronous runtime used by axum/tower/hyper. See e.g Spawning | Tokio - An asynchronous Rust runtime for more info.

Ok, this sounds reasonable.
But there is Async scoped, which gives "scoped tokio tasks".

By my intuitions, all those scoped variants of tasks and endpoints are both sound and better suited than there non-scoped variants.

Is this correct?

In my reality, I never need a non-scoped thread, and Arc feels like a hack. Everything (tasks/threads) is joined by its creator.

(If I need shared mutability, Arc mutex feels correct.)

Please be aware of the limitations of the async-scoped crate:

Yes, I'm aware of the limitations.
Those are fine for my use cases.
But, since there is no axum variant supporting those, this doesn't apply.

So far, we established:

  1. There is no "scoped routes" in axum, because there is no "scoped task" in tokio.
  2. There are PoC crstes implementing "scoped tasks" with limitations.

So, my question seems to be:
Can there be "scoped tasks" without limitations?

Not in safe Rust as it exists today. That requires concepts of "async Drop" or "unforgettable types" that Rust doesn't have.

2 Likes

See also:

3 Likes