提问人:Karan Kumar 提问时间:11/3/2023 更新时间:11/3/2023 访问量:52
Axum pg通过共享状态连接
Axum pgconnection through shared state
问:
我想通过应用程序级别状态将 PgConnection 共享到所有路由和服务 尝试实现依赖注入。
我面临的问题是,需要连接。
而 axum 用于在它旋转的所有进程中提供状态。sqlx
mut reference
Arc
immutable reference
这迫使我使用只是为了让我有可变的引用来满足Arc<Mutex<PgConnection>>
sqlx
pub struct AppState {
pub db_connection: Arc<Mutex<PgConnection>>,
pub jwt: JWTSettings,
}
这就是我在路线中使用它的方式
pub async fn sign_up(
State(state): State<Arc<AppState>>,
Json(signup_payload): Json<SignupPayload>,
) -> Result<Json<LoginResponse>, StatusCode> {
let mut connection = state.db_connection.lock().unwrap();
sqlx::query!("select * from users where username=$1", signup_payload.username)
.fetch_one(&mut*connection)
.await
.map_err(|err| {
println!("ERROR: Unable to execute the query {:?}", err);
return StatusCode::INTERNAL_SERVER_ERROR;
});
问题我不希望路由/线程保持连接,否则就没有工作进程可以并行运行的点。lock
答:
2赞
Chayim Friedman
11/3/2023
#1
不应使用单个连接,而应使用连接池。这将允许有效地重用连接。
pub struct AppState {
pub db_pool: sqlx::PgPool,
pub jwt: JWTSettings,
}
pub async fn sign_up(
State(state): State<Arc<AppState>>,
Json(signup_payload): Json<SignupPayload>,
) -> Result<Json<LoginResponse>, StatusCode> {
let mut connection = state.db_pool.acquire().await.unwrap();
sqlx::query!(
"select * from users where username=$1",
signup_payload.username
)
.fetch_one(&mut *connection)
.await
.map_err(|err| {
println!("ERROR: Unable to execute the query {:?}", err);
return StatusCode::INTERNAL_SERVER_ERROR;
});
}
0赞
Yoric
11/3/2023
#2
一般来说,无论是在 Rust 还是其他编程语言中,你永远不应该保持长期的连接。例如,如果数据库上有维护,这可能会破坏您的应用程序。
相反,您应该保留一个连接池。如果连接可用,这将重用连接,否则它将连接您。
如果我理解正确,您正在使用 sqlx。它支持开箱即用的池。
评论
0赞
Karan Kumar
11/3/2023
您能否解释一下,当您说“如果连接可用,这将重用连接,否则它将连接您”时,您的意思是什么?
1赞
Yoric
11/3/2023
数据库连接池的一般思想是,您要求它为您提供连接。如果这是您第一次连接到数据库,池将创建一个连接并返回该连接。一旦您停止使用此连接(即在请求结束时),池将保持连接活动一段时间,以防您再次需要它。如果连接断开(例如,由于数据库服务器已重新启动),或者如果所有连接当前都处于繁忙状态,则下次向池请求连接时,它将重新连接您。
0赞
Yoric
11/3/2023
如果您赶时间,请使用弗里德曼@Chayim解决方案:)它使用数据库连接池。
评论