由於本文當下 2024/05/01 在 Rocket Async Diesel 的 Library 底下還沒有支援從內部取得 Connection 的方法,若不想重新寫一個 Connection 當作 Wrap 的情況下,可以把記憶體直接裝到新的型別變數中。
強制轉型記憶體的方法 Unsafe
實際上在 Rocket 的範例中,要讓每個進入 Function 的 Router 同時接收 DbConn 參數,大多都是由 from_request [1] 這個地方從 "request: &'r rocket::Request<'_>" 這個方法裡面取的 DbConn,例如:
async fn from_request( request: &'r rocket::Request<'_>, ) -> rocket::request::Outcome<Self, Self::Error> { let mut db = request.guard::<DbConn>().await;
但是,除此之外,要不透過 http 的 API Router 打進來去執行取得共用的 DbConn 卻很困難,例如有外 Cronjob 或是其他 Threading 去控制背景工作。
以下是一個方法,透過 Rocket 啟動時的 on_ignite ,可以讓 MyDb 從 rocket 取得 context,但是由於缺少型標轉換,因此可以透過 unsafe { std::mem::transmute }} 的方法強制轉換到該變數中。
use rocket_db_pools::diesel::{ pooled_connection::{ deadpool::{self, Object}, AsyncDieselConnectionManager, }, AsyncConnection, AsyncMysqlConnection, MysqlPool, Pool, SimpleAsyncConnection, }; #[derive(Database)] #[database("my_db")] pub struct MyDb(MysqlPool); pub type DbConn = Connection<MainDb>; rocket::build() .attach(MyDb::init()) .attach(AdHoc::on_ignite("Seeding database", |rocket| async move { let db = MyDb::fetch(&rocket).unwrap(); // Object<AsyncDieselConnectionManager<AsyncMysqlConnection>> let mut conn = db.get().await.unwrap(); let mut clone_conn = db.clone().get().await.unwrap(); let mut casted_conn: DbConn = unsafe { std::mem::transmute(clone_conn) };
// 此時 Diesel 上的操作可以從這裡開始做了 })
重寫 Connection
或者,可以重新寫一個 Conncetion 讓 DbConn 的 Type 是自己 Wrap 上來的:
use rocket_db_pools::{Database, Pool}; pub struct Connection<D: Database>(<D::Pool as Pool>::Connection); impl<D: Database> Connection<D> { pub async fn get (db: &D) -> Self { Connection(db.get().await.unwrap().into()) } }
當這麼做以後,事實上 DbConn 接下來就可以直接使用 get 取得連線:
#[derive(Database)] #[database("my_db")] pub struct MyDb(MysqlPool); pub type DbConn = Connection<MainDb>; AdHoc::on_ignite("Init", |rocket| async move { let db = MyDb::fetch(&rocket).expect("Failed"); let conn = DbConn::get(db).await.expect("Failed"); tokio::spawn(async move { do_something(conn, tasks) .await .expect("Failed to run rescheduler"); }); rocket })
Reference:
[1]: https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest
沒有留言:
張貼留言