I'm using the recommended rocket_db_pools crate to create a database pool and attach it to Rocket e.g.
#[derive(Database)]
#[database("birthdays")]
struct DB(sqlx::SqlitePool);
// in main
rocket::build()
.attach(DB::init())
I would like to access the same database pool outside of the context of Rocket. I'm attempting to spawn a separate tokio task that runs alongside Rocket and does some additional background work e.g.
async fn main() -> _ {
rocket::tokio::spawn(async {
// access DB pool here
})
rocket::build()
// ...
}
Is there a way to initialize a sqlx::SqlitePool and easily provide it to both the background task and Rocket so I can still leverage the automatic #[derive(Database)] goodies that rocket_db_pools provides?
As a relative rust beginner I'm having a hard time reading through the traits and understanding if there is a way to do so that doesn't require doing it fully custom by creating a pool, writing my own impl FromRequest, etc.
I found an alternative based on the example from rocket_sync_db_pools which I adapted for the differences with rocket_db_pools.
It uses a fairing to get access to the Database after it has been initialized and then clones the wrapped SqlitePool to move into the task.
#[derive(Database)]
#[database("birthdays")]
struct DB(sqlx::SqlitePool);
// in main
rocket::build()
.attach(DB::init())
.attach(AdHoc::try_on_ignite("Background job", |rocket| async {
let pool = match DB::fetch(&rocket) {
Some(pool) => pool.0.clone(), // clone the wrapped pool
None => return Err(rocket),
};
rocket::tokio::task::spawn(async move {
loop {
if let Ok(mut conn) = pool.acquire().await {
let results = sqlx::query_as::<_, Birthday>(
"SELECT name, birthday, account_id FROM birthdays",
)
.fetch_all(&mut conn)
.await
.expect("query should succeed");
debug!("selected from birthdays: {:?}", results);
}
sleep(Duration::from_secs(10)).await;
}
});
Ok(rocket)
}))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With