Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres backend in Axum: Cannot start a runtime from within a runtime. #275

Open
RobertoMaurizzi opened this issue Oct 20, 2024 · 2 comments

Comments

@RobertoMaurizzi
Copy link

RobertoMaurizzi commented Oct 20, 2024

Hi!

I'm still going at using Butane within a Leptos/Axum project.
I got to a decent point where I'd like to have more visibility on database changes and types, so I switched from SQLite to Postgres.
Unfortunately when I try to use the database I now get a:

thread '<unnamed>' panicked at /home/robm/.cargo/registry/src/index.crates.io-6f17d22bba15001f/postgres-0.19.9/src/connection.rs:66:22:
Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.

and a backtrace. Searching around I found tokio-rs/tokio#2194 where they say it's quite normal since the postgres crate doesn't support async, so if you try to await something you'll cause this... they recommend using a tokio-postgres crate instead.

Did anyone see this before? Could it be I'm doing something wrong in how I manage the r2d2 connection instead?

@Electron100
Copy link
Owner

That is unfortunately a known issue. Here's what's going on

  1. Butane is not async aware/capable in its released / main-branch form.
  2. Axum requires async (as does Actix and many other Rust web frameworks).
  3. Butane's Postgres support uses the postgres crate
  4. The postgres crate is actually a wrapper around tokio-postgres and essentially provides a synchronous interface by using block_on from a Tokio runtime.
  5. This means that the layering goes async (Axum) -> sync (Butane) -> async with a different runtime (tokio-postgres). As you've discovered, this nesting is causes Tokio to explode.

I would like to offer async capabilities in Butane. Progress has been slow I'm afraid due to both lack of time on my part as well as complications from my desire to offer both sync and async interfaces at the same time, without duplicating all the code and without major breaking changes to the existing sync APIs.
Why both sync and async when most major web frameworks are async-oriented? It stems from Butane's origins as a simple interface for object persistence -- I'd like Butane to be an equally valid choice for data persistence in local agents or CLIs which will typically use SQLite and have no need for async.

However, async with Butane is actually getting really close, and is ready for feedback! You can check it out on the async-wip branch. As of this week, I expect the API to be stable, although that's not a guarantee. If you're interested in giving it a whirl, it should solve your issues with Axum.

On the other hand, if you're not up for being an early adopter, it should be possible to use channels to run your database operations on a separate thread to avoid the runtime nesting. If you'd like to chat more about that I'm happy to provide some pointers, as that's similar to what I've done in the async-wip branch of Butane to provide full parity between sync and async (e.g. you can use sqlite with async and Butane runs it on its own dedicated thread).

See also #13

@RobertoMaurizzi
Copy link
Author

Nice!
Unfortunately I'm still quite new to both Rust and working with Leptos/Axum, plus free time to work on my project is limited, so I'm not sure what I'll be able to do, but I'll try to replace r2d2 with deadpool/bb8 and give the feedback I can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants