-
I'm currently working inside a workspace where I have a main actix-web program and another one using rust-celery. One crate is bootstrapped with If I choose the sqlx As suggested, I switched the runtime to use the same features in both project. I choosed 'runtime-tokio` in both crates. I now have in my actix-web based crate (using the actix runtime), a sqlx dependency configured with the However, I'm new to this and I would like to know if I am not doing a mistake by doing this? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
We use this in our projects internally. You can even have both runtimes going in the same binary. In fact, the Actix runtime is just a wrapper around the Tokio runtime that forces it into single-threaded mode, and Tokio's notion of "current runtime" is set on a per-thread basis, so technically you could have a pool of threads each with its own Actix runtime if you want. Since the Actix runtime is single-threaded, if we have a lot of background work in our app that we don't want clogging up the Actix thread, we'll start a Tokio threaded runtime in the background and spawn tasks into that. The Our basic app structure looks kinda like this:
mod http;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let db: sqlx::PgPool = /* create PgPool */;
sqlx::migrate!().run(&db).await?;
// spawn background tasks
tokio::spawn(async move { /* ... */ };
// this causes the current thread to switch from the Tokio runtime to the Actix runtime
// as the Tokio threaded runtime takes this out of its own core thread pool that runs async tasks
tokio::task::block_in_place(move || http::run(db))
}
// this attribute doesn't actually care if it's decorating the crate's `main()` function
// it'll turn any `async fn` into a blocking function that starts an Actix runtime and wait until it completes
#[actix_web::main]
pub async fn run(db: PgPool) -> anyhow::Result<()> {
let db = actix_web::web::Data::new(db);
HttpServer::new(move || App::new().app_data(db.clone())/* ... add services and other app data */)
.bind("0.0.0.0:8080")?
.run()
.await?;
Ok(())
} |
Beta Was this translation helpful? Give feedback.
We use this in our projects internally. You can even have both runtimes going in the same binary. In fact, the Actix runtime is just a wrapper around the Tokio runtime that forces it into single-threaded mode, and Tokio's notion of "current runtime" is set on a per-thread basis, so technically you could have a pool of threads each with its own Actix runtime if you want.
Since the Actix runtime is single-threaded, if we have a lot of background work in our app that we don't want clogging up the Actix thread, we'll start a Tokio threaded runtime in the background and spawn tasks into that. The
tokio::net::TcpStream
that underlies SQLx's connection types doesn't seem to mind being moved back…