Axum pg通过共享状态连接

Axum pgconnection through shared state

提问人:Karan Kumar 提问时间:11/3/2023 更新时间:11/3/2023 访问量:52

问:

我想通过应用程序级别状态将 PgConnection 共享到所有路由和服务 尝试实现依赖注入。

我面临的问题是,需要连接。 而 axum 用于在它旋转的所有进程中提供状态。sqlxmut referenceArcimmutable 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

锈-tokio 锈-阿克苏姆

评论


答:

2赞 Chayim Friedman 11/3/2023 #1

不应使用单个连接,而应使用连接池。这将允许有效地重用连接。

SQLX 提供对池的支持

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解决方案:)它使用数据库连接池。